day108:MoFang:首頁檢測使用者是否登入&在專案中使用MongoDB&使用者頁面更新使用者資訊&交易密碼介面實現
阿新 • • 發佈:2020-12-11
目錄
1.首頁頁面也要檢測使用者是否登入
2.在flask中使用MongoDB
3.使用者頁面更新使用者資訊
4.交易密碼介面/密碼修改介面/暱稱修改介面初始化
5.交易密碼實現
1.首頁頁面也要檢測使用者是否登入
1.在index.html中新增check_user_login方法
在index.html頁面中呼叫checkout函式,如果回撥函式傳來1005狀態碼,則刪除對應token,讓使用者重新進行登入
html/index.html
,程式碼;
created(){ this.check_user_login(); }, methods:{ // 首頁檢測使用者是否登入 check_user_login(){ let token = this.game.get("access_token") || this.game.fget("access_token"); this.game.checkout(this, token, (new_access_token)=>{ if(new_access_token.errno == 1005){ this.game.save({"access_token":""}); this.game.fremove("access_token"); } }); },
2.修改main.js中checkout函式
當檢查使用者登入狀態時,如果使用者點選取消登入,則返回1005狀態碼.
class Game{ // 驗證使用者token是否存在或者是否失效的功能 checkout(vm, token, callback){ vm.axios.post("",{ "jsonrpc": "2.0", "id": vm.uuid(), "method": "User.check", "params": {} },{ headers:{ Authorization: "jwt " + token, } }).then(response=>{ if(parseInt(response.data.result.errno) === 1005){ api.actionSheet({ title: '本次登陸超時,是否更新登陸狀態?', cancelTitle: '取消登陸', destructiveTitle: '更新登陸狀態', }, (ret, err)=>{ if( ret.buttonIndex == 1 ){ this.get_acccess_by_refresh(vm, callback); }else{ // ******** callback({"errno":1005,"errmsg":"登陸超時!"}); } }); }else if (parseInt(response.data.result.errno) === 1000){ callback(token); } return false; }).catch(error=>{ this.print(error); }); } get_acccess_by_refresh(vm, callback){ var token = this.get("refresh_token") || this.fget("refresh_token"); if( !token ){ return false; } vm.axios.post("",{ "jsonrpc": "2.0", "id": vm.uuid(), "method": "User.refresh", "params": {} },{ headers:{ Authorization: "jwt " + token, } }).then(response=>{ if(response.data.result.errno===1000){ this.save({"access_token": response.data.result.access_token}); callback(response.data.result.access_token); } }) }
2.在flask中使用MongoDB
1.安裝
pip install Flask-PyMongo
2.初始化和配置
application/__init__.py
,程式碼:
from flask_pymongo import PyMongo # mongoDB mongo = PyMongo() def init_app(config_path): """全域性初始化""" # 資料庫初始化 db.init_app(app) app.db = db redis.init_app(app) mongo.init_app(app) # 初始化mongo
`application/settings/dev.py
`,程式碼:
from . import InitConfig class Config(InitConfig): """專案開發環境下的配置""" # mongoDB配置資訊 MONGO_URI = "mongodb://127.0.0.1:27017/mofang"
3.在使用者修改個人資訊[頭像]時, 更新歷史記錄到mongodb
application/apps/users/views.py
,程式碼:
import base64, uuid,os from application import mongo from datetime import datetime @jsonrpc.method("User.avatar.update") @jwt_required # 驗證jwt def update_avatar(avatar): """獲取使用者資訊""" # 1. 接受客戶端上傳的頭像資訊 ext = avatar[avatar.find("/")+1:avatar.find(";")] # 資源格式 b64_avatar = avatar[avatar.find(",")+1:] b64_image = base64.b64decode(b64_avatar) filename = uuid.uuid4() static_path = os.path.join( current_app.BASE_DIR,current_app.config["STATIC_DIR"] ) with open("%s/%s.%s" % (static_path, filename,ext),"wb") as f: f.write(b64_image) # 2.判斷使用者是否存在 current_user_id = get_jwt_identity() user = User.query.get(current_user_id) if user is None: return { "errno": status.CODE_NO_USER, "errmsg": message.user_not_exists, } # 3.將使用者頭像存到mysql資料庫中 user.avatar = "%s.%s" % (filename,ext) db.session.commit() # ***4.新增修改記錄到MongoDB***! document = { "user_id": user.id, "user_name": user.name, "user_nikcname": user.nickname, "updated_time": datetime.now().timestamp(), # 修改時間 "avatar": avatar, # 圖片內容 "type": "avatar", # 本次操作的型別 } mongo.db.user_info_history.insert_one(document) return { "errno": status.CODE_OK, "errmsg": message.avatar_save_success, "avatar": "%s.%s" % (filename,ext) }
3.使用者頁面更新使用者資訊
1.將nickname和avatar改為動態的
2.並且在user.html中新增之前已經寫過的change_avatar函式和get_user_info函式
<!DOCTYPE html> <html> <head> <title>使用者中心</title> <meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no"> <meta charset="utf-8"> <link rel="stylesheet" href="../static/css/main.css"> <script src="../static/js/vue.js"></script> <script src="../static/js/axios.js"></script> <script src="../static/js/main.js"></script> <script src="../static/js/uuid.js"></script> <script src="../static/js/settings.js"></script> </head> <body> <div class="app user" id="app"> <div class="bg"> <img src="../static/images/bg0.jpg"> </div> <img class="back" @click="goto_index" src="../static/images/user_back.png" alt=""> <img class="setting" @click="goto_setting" src="../static/images/setting.png" alt=""> <div class="header"> <div class="info"> <div class="avatar"> <img class="avatar_bf" src="../static/images/avatar_bf.png" alt=""> <img class="user_avatar" :src="avatar" alt=""> <img class="avatar_border" src="../static/images/avatar_border.png" alt=""> </div> <p class="user_name">{{nickname}}</p> </div> <div class="wallet"> <div class="balance"> <p class="title"><img src="../static/images/money.png" alt="">錢包</p> <p class="num">99,999.00</p> </div> <div class="balance"> <p class="title"><img src="../static/images/integral.png" alt="">果子</p> <p class="num">99,999.00</p> </div> </div> <div class="invite"> <img class="invite_btn" src="../static/images/invite.png" alt=""> </div> </div> <div class="menu"> <div class="item"> <span class="title">我的主頁</span> <span class="value">檢視</span> </div> <div class="item"> <span class="title">任務列表</span> <span class="value">75%</span> </div> <div class="item"> <span class="title">收益明細</span> <span class="value">檢視</span> </div> <div class="item"> <span class="title">實名認證</span> <span class="value">未認證</span> </div> <div class="item"> <span class="title">問題反饋</span> <span class="value">去反饋</span> </div> </ul> </div> </div> <script> apiready = function(){ init(); new Vue({ el:"#app", data(){ return { nickname:"", avatar:"", prev:{name:"",url:"",params:{}}, current:{name:"user",url:"user.html",params:{}}, } }, created(){ this.get_user_info(); this.change_avatar(); }, methods:{ change_avatar(){ api.addEventListener({ name: 'change_avatar' }, (ret, err)=>{ if( ret ){ var token = this.game.get("access_token") || this.game.fget("access_token"); this.avatar = `${this.settings.avatar_url}?sign=${ret.value.avatar}&token=${token}`; } }); }, get_user_info(){ var token = this.game.get("access_token") || this.game.fget("access_token"); // 獲取當前登陸使用者基本資訊 this.axios.post("",{ "jsonrpc": "2.0", "id": this.uuid(), "method": "User.info", "params": {} },{ headers:{ Authorization: "jwt " + token, } }).then(response=>{ var res = response.data.result; this.game.print(res); if(parseInt(res.errno) === 1000){ this.nickname = res.nickname; this.avatar = `${this.settings.avatar_url}?sign=${res.avatar}&token=${token}`; } }) }, goto_index(){ // 返回首頁 this.game.outWin("user"); }, goto_setting(){ // 進入設定 this.game.goFrame("setting","setting.html", this.current); } } }); } </script> </body> </html>使用者頁面更新使用者資訊
解決頭像圓角問題
解決頭像圓角問題,可以通過css修改樣式. main.css
,程式碼:
.user .info .user_avatar{ position: absolute; z-index: 1; width: 4.56rem; height: 4.56rem; margin: auto; top: 0; bottom: 0; left: 0; right: 0; border-radius: 1rem; }
4.交易密碼介面/密碼修改介面/暱稱修改介面初始化
1.配置頁面點選交易/密碼修改/暱稱,進入到相應介面
配置頁面中點選交易密碼/密碼修改/暱稱,進入相應頁面。html/setting.html
,程式碼:
<!DOCTYPE html> <html> <head> <title>使用者中心</title> <meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no"> <meta charset="utf-8"> <link rel="stylesheet" href="../static/css/main.css"> <script src="../static/js/vue.js"></script> <script src="../static/js/axios.js"></script> <script src="../static/js/main.js"></script> <script src="../static/js/uuid.js"></script> <script src="../static/js/settings.js"></script> </head> <body> <div class="app user setting" id="app"> <div class="bg"> <img src="../static/images/form_bg.png"> </div> <img class="back" @click="goto_home" src="../static/images/user_back.png" alt=""> <div class="form"> <div class="item avatar" @click="update_avatar_frame"> <span class="title">頭像</span> <span class="goto">></span> <span class="value"> <img :src="avatar" alt=""> </span> </div> <div class="item" @click="update_nickname_frame"> <span class="title">暱稱</span> <span class="goto">></span> <span class="value">{{nickname}}</span> </div> <div class="item"> <span class="title">手機號</span> <span class="goto">></span> <span class="value">{{mobile}}</span> </div> <div class="item" @click="update_password_frame"> <span class="title">登陸密碼</span> <span class="value"></span> <span class="goto">></span> </div> <div class="item" @click="update_transaction_password_frame"> <span class="title">交易密碼</span> <span class="value"></span> <span class="goto">></span> </div> <div class="item"> <span class="title">地址管理</span> <span class="value"></span> <span class="goto">></span> </div> <div class="item"> <span class="title">裝置管理</span> <span class="value"></span> <span class="goto">></span> </div> <div class="item logout"> <img @click="change_account" src="../static/images/change_account.png" alt=""> <p @click="logout">退出賬號</p> </div> </div> </div> <script> apiready = function(){ init(); new Vue({ el:"#app", data(){ return { nickname: "", mobile: "", avatar: "../static/images/avatar.png", prev:{name:"",url:"",params:{}}, current:{name:"setting",url:"setting.html",params:{}}, } }, created(){ this.get_user_info(); this.change_avatar(); }, methods:{ get_user_info(){ var token = this.game.get("access_token") || this.game.fget("access_token"); // 獲取當前登陸使用者基本資訊 this.axios.post("",{ "jsonrpc": "2.0", "id": this.uuid(), "method": "User.info", "params": {} },{ headers:{ Authorization: "jwt " + token, } }).then(response=>{ var res = response.data.result; this.game.print(res); if(parseInt(res.errno) === 1000){ this.nickname = res.nickname; this.avatar = `${this.settings.avatar_url}?sign=${res.avatar}&token=${token}`; this.mobile = res.mobile; } }) }, change_avatar(){ api.addEventListener({ name: 'change_avatar' }, (ret, err)=>{ if( ret ){ var token = this.game.get("access_token") || this.game.fget("access_token"); this.avatar = `${this.settings.avatar_url}?sign=${ret.value.avatar}&token=${token}`; } }); }, goto_home(){ // this.game.outFrame("setting"); this.game.goFrame("user","user.html",this.current); }, change_account(){ // 切換賬號 this.game.goFrame("login","login.html", this.current); }, logout(){ // 退出賬號 api.actionSheet({ title: '您確認要退出當前登入嗎?', cancelTitle: '取消', destructiveTitle: '退出登入' }, (ret, err)=>{ if( ret ){ this.game.print(ret); // 取消為2 if(ret.buttonIndex==1){ this.game.save({"access_token":"","refresh_token":""}); this.game.fremove(["access_token","refresh_token"]); this.game.outWin("user"); } } }); }, update_avatar_frame(){ // 顯示修改頭像的頁面frame this.game.goFrame("avatar","avatar.html", this.current,null,{ type:"push", //動畫型別(詳見動畫型別常量) subType:"from_top", //動畫子型別(詳見動畫子型別常量) duration:300 //動畫過渡時間,預設300毫秒 }); }, update_transaction_password_frame(){ this.game.goFrame("transaction_password","transaction_password.html", this.current,null,{ type:"push", subType:"from_top", duration:300 }); }, update_password_frame(){ this.game.goFrame("password","password.html", this.current,null,{ type:"push", subType:"from_top", duration:300 }); }, update_nickname_frame(){ this.game.goFrame("password","password.html", this.current,null,{ type:"push", subType:"from_top", duration:300 }); } } }); } </script> </body> </html>配置頁面點選不同項進入不同頁面
2.交易頁面初始化
<!DOCTYPE html> <html> <head> <title>使用者中心</title> <meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no"> <meta charset="utf-8"> <link rel="stylesheet" href="../static/css/main.css"> <script src="../static/js/vue.js"></script> <script src="../static/js/axios.js"></script> <script src="../static/js/main.js"></script> <script src="../static/js/uuid.js"></script> <script src="../static/js/settings.js"></script> </head> <body> <div class="app frame avatar update_password" id="app"> <div class="box"> <p class="title">交易密碼</p> <img class="close" @click="close_frame" src="../static/images/close_btn1.png" alt=""> <div class="content"> <input class="password" type="text" v-model="password" placeholder="交易密碼...."> <input class="password password2" type="text" v-model="password2" placeholder="確認交易密碼...."> </div> <img @click="update_password_commit" class="btn" src="../static/images/yes.png" alt=""> </div> </div> <script> apiready = function(){ init(); new Vue({ el:"#app", data(){ return { password:"", password2:"", prev:{name:"",url:"",params:{}}, current:{name:"transaction_password",url:"transaction_password.html",params:{}}, } }, methods:{ close_frame(){ this.game.outFrame("transaction_password"); }, update_password_commit(){ // 提交使用者密碼 } } }); } </script> </body> </html>交易頁面transaction_password.html初始化
交易介面CSS樣式
.update_nickname .nickname, .update_password .password { margin: 8rem 4.4rem 4rem; width: 19.50rem; height: 4rem; line-height: 4rem; background-color: #cc9966; outline: none; border: 1px solid #330000; text-align: center; font-size: 1.5rem; color: #ffffcc; } .update_password .password{ margin-top: 5.6rem; margin-bottom: 0.4rem; } .update_password .password2{ margin-top: 0.4rem; }交易介面CSS樣式
3.密碼修改介面初始化
<!DOCTYPE html> <html> <head> <title>使用者中心</title> <meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no"> <meta charset="utf-8"> <link rel="stylesheet" href="../static/css/main.css"> <script src="../static/js/vue.js"></script> <script src="../static/js/axios.js"></script> <script src="../static/js/main.js"></script> <script src="../static/js/uuid.js"></script> <script src="../static/js/settings.js"></script> </head> <body> <div class="app frame avatar update_password" id="app"> <div class="box"> <p class="title">修改密碼</p> <img class="close" @click="close_frame" src="../static/images/close_btn1.png" alt=""> <div class="content"> <input class="password" type="text" v-model="password" placeholder="原密碼...."> <input class="password password2" type="text" v-model="password2" placeholder="新密碼...."> </div> <img @click="update_password_commit" class="btn" src="../static/images/yes.png" alt=""> </div> </div> <script> apiready = function(){ init(); new Vue({ el:"#app", data(){ return { password:"", password2:"", prev:{name:"",url:"",params:{}}, current:{name:"password",url:"password.html",params:{}}, } }, methods:{ close_frame(){ this.game.outFrame("password"); }, update_password_commit(){ // 提交使用者密碼 } } }); } </script> </body> </html>密碼修改介面password.html
4.暱稱修改介面初始化
<!DOCTYPE html> <html> <head> <title>使用者中心</title> <meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no"> <meta charset="utf-8"> <link rel="stylesheet" href="../static/css/main.css"> <script src="../static/js/vue.js"></script> <script src="../static/js/axios.js"></script> <script src="../static/js/main.js"></script> <script src="../static/js/uuid.js"></script> <script src="../static/js/settings.js"></script> </head> <body> <div class="app frame avatar update_nickname" id="app"> <div class="box"> <p class="title">修改暱稱</p> <img class="close" @click="close_frame" src="../static/images/close_btn1.png" alt=""> <div class="content"> <input class="nickname" type="text" v-model="nickname" placeholder="輸入暱稱...."> </div> <img @click="update_nickname_commit" class="btn" src="../static/images/yes.png" alt=""> </div> </div> <script> apiready = function(){ init(); new Vue({ el:"#app", data(){ return { nickname:"", prev:{name:"",url:"",params:{}}, current:{name:"nickname",url:"nickname.html",params:{}}, } }, methods:{ close_frame(){ this.game.outFrame("nickname"); }, update_nickname_commit(){ // 提交使用者暱稱 } } }); } </script> </body> </html>暱稱修改介面nickname.html初始化
5.交易密碼實現
1.模型中新增交易密碼欄位
模型中,新增一個交易密碼的欄位.users.models
程式碼:
from werkzeug.security import generate_password_hash, check_password_hash from application.utils.models import BaseModel,db class User(BaseModel): """使用者基本資訊""" # 新增一個交易密碼的欄位 _transaction_password = db.Column(db.String(255), comment="交易密碼") @property def transaction_password(self): return self._transaction_password @transaction_password.setter def transaction_password(self, rawpwd): """密碼加密""" self._transaction_password = generate_password_hash(rawpwd) def check_transaction_password(self, rawpwd): """驗證密碼""" return check_password_hash(self.transaction_password, rawpwd)
資料遷移,命令:
python manage.py db migrate -m "add user tansaction password" python manage.py db upgrade
2.編寫交易密碼後端介面
檢視中編寫交易密碼修改的介面,users.views.
,程式碼
@jsonrpc.method("User.transaction.password") @jwt_required # 驗證jwt def transaction_password(password1, password2,old_password=None): """ 交易密碼的初始化和修改 1. 剛註冊的使用者,沒有交易密碼,所以此處填寫的是新密碼 2. 已經有了交易密碼的使用者,修改舊的交易密碼 """ # 1.判斷兩次輸入密碼是否一致 if password1 != password2: return { "errno": status.CODE_TRANSACTION_PASSWORD_ERROR, "errmsg": message.transaction_password_not_match } # 2.判斷使用者是否存在 current_user_id = get_jwt_identity() user = User.query.get(current_user_id) if user is None: return { "errno": status.CODE_NO_USER, "errmsg": message.user_not_exists, } # 3.如果之前有存在交易密碼,則需要驗證舊密碼 if user.transaction_password: # 去資料庫檢視使用者是否有舊的交易密碼 """修改""" # 驗證舊密碼 ret = user.check_transaction_password(old_password) if ret == False: # 如果驗證舊密碼失敗 return { "errno": status.CODE_PASSWORD_ERROR, "errmsg": message.transaction_password_error } """設定交易密碼""" user.transaction_password = password1 db.session.commit() return { "errno": status.CODE_OK, "errmsg": message.ok }
3.客戶端提交交易密碼變更後端使用者資訊
<!DOCTYPE html> <html> <head> <title>使用者中心</title> <meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no"> <meta charset="utf-8"> <link rel="stylesheet" href="../static/css/main.css"> <script src="../static/js/vue.js"></script> <script src="../static/js/axios.js"></script> <script src="../static/js/main.js"></script> <script src="../static/js/uuid.js"></script> <script src="../static/js/settings.js"></script> </head> <body> <div class="app frame avatar update_password" id="app"> <div class="box"> <p class="title">交易密碼</p> <img class="close" @click="close_frame" src="../static/images/close_btn1.png" alt=""> <div class="content" v-if="is_set_password"> <input class="password" type="password" v-model="old_password" placeholder="舊交易密碼...."> <input class="password password2" type="password" v-model="password1" placeholder="新交易密碼...."> <input class="password password2" type="password" v-model="password2" placeholder="確認新交易密碼...."> </div> <div class="content" v-else> <input class="password" type="password" v-model="password1" placeholder="交易密碼...."> <input class="password password2" type="password" v-model="password2" placeholder="確認交易密碼...."> </div> <img @click="update_password_commit" class="btn" src="../static/images/yes.png" alt=""> </div> </div> <script> apiready = function(){ init(); new Vue({ el:"#app", data(){ return { is_set_password: true, old_password: "", // 舊交易密碼 password1:"", // 新交易密碼 password2:"", // 確認新交易密碼 prev:{name:"",url:"",params:{}}, current:{name:"transaction_password",url:"transaction_password.html",params:{}}, } }, created(){ if( this.game.fget("is_set_transaction_password") === "false"){ this.is_set_password = false; } }, methods:{ close_frame(){ this.game.outFrame("transaction_password"); }, update_password_commit(){ // 1.提交使用者新密碼 params = { password1: this.password1, password2: this.password2, } // 2.如果不是第一次設定密碼,需要將舊密碼也提交到後端 if(this.is_set_password){ params.old_password = this.old_password; } // 3.向交易密碼後端介面傳送請求 var token = this.game.get("access_token") || this.game.fget("access_token"); this.axios.post("",{ "jsonrpc": "2.0", "id": this.uuid(), "method": "User.transaction.password", "params": params },{ headers:{ Authorization: "jwt " + token, } }).then(response=>{ var res = response.data.result; if(parseInt(res.errno) === 1000){ this.game.fsave({"is_set_transaction_password":true}); this.game.outFrame("transaction_password"); }else{ api.alert({ title: '錯誤!', msg: res.errmsg, }, function(ret, err){ }); this.game.print(res.errno); } }).catch(error=>{ this.game.print(error); }); } } }); } </script> </body> </html>
4.把交易密碼更變歷史記錄到Mongodb中
@jsonrpc.method("User.transaction.password") @jwt_required # 驗證jwt def transaction_password(password1, password2,old_password=None): """ 交易密碼的初始化和修改 1. 剛註冊的使用者,沒有交易密碼,所以此處填寫的是新密碼 2. 已經有了交易密碼的使用者,修改舊的交易密碼 """ if password1 != password2: return { "errno": status.CODE_TRANSACTION_PASSWORD_ERROR, "errmsg": message.transaction_password_not_match } current_user_id = get_jwt_identity() user = User.query.get(current_user_id) if user is None: return { "errno": status.CODE_NO_USER, "errmsg": message.user_not_exists, } # 1.如果之前有存在交易密碼,則需要驗證舊密碼 if user.transaction_password: """修改""" # 驗證舊密碼 ret = user.check_transaction_password(old_password) if ret == False: return { "errno": status.CODE_PASSWORD_ERROR, "errmsg": message.transaction_password_error } """設定交易密碼""" user.transaction_password = password1 db.session.commit() # ***2.新增交易密碼的修改記錄,為了保證安全,僅僅記錄舊密碼!*** if old_password: document = { "user_id": user.id, "user_name": user.name, "user_nikcname": user.nickname, "updated_time": datetime.now().timestamp(), # 修改時間 "transaction_password": old_password, # 變更內容 "type": "transaction_password", # 本次操作的型別 } mongo.db.user_info_history.insert_one(document) return { "errno": status.CODE_OK, "errmsg": message.ok }
&n