託管小程序雲開發-031-雲開發 - 用戶登錄與用戶openId記錄入庫實現

薇薇和希希 發佈 2022-09-27T20:34:42.978107+00:00

在需要用戶登錄的頁面,在按鈕或者進入頁面時,檢測用戶是否登錄,如果沒有登錄,跳轉到用戶中心,引導用戶登錄。

一、需求分析

1、前言

基於微信小程序雲開發之下的新用戶註冊,用戶登錄的概念其實已經不像傳統的網站開發,僅需要幾十行代碼就可以做到新用戶註冊入庫、老用戶信息獲取(登錄)的功能。更加快速的建立小程序內的用戶體系。

2、思路分析

用戶 每次打開小程序,在app.js檢測用戶是否登錄,並且將用戶信息和登錄狀態保存到緩存和app.globalData數據中;

在需要用戶登錄的頁面,在按鈕或者進入頁面時,檢測用戶是否登錄,如果沒有登錄,跳轉到用戶中心,引導用戶登錄。

二、雲開發實現

1、創建用戶表tb_user(已完成)

只需要在雲端創建一個空表(集合)

欄位名

數據類型

內容模型

含義

備註

_id

string


主鍵

系統生成

openId

string

#單行字符串

用戶微信openId


phone

string

#電話號碼

手機號碼


nickName

string

#單行字符串

微信暱稱

'':非授權用戶,不為空:授權用戶

gender

number

#數字

性別


avatarUrl

string

#圖片.HTTPS

微信頭像


status

number

#布爾

狀態

0:正常,1:禁止

isAdmin

boolean

#布爾

是否是管理員

false:不是,true:是

create_time

number

#日期與時間.時間戳

創建時間


update_time

number

#日期與時間.時間戳

修改時間


last_login_time

number

#日期與時間.時間戳

最後登錄時間


last_login_ip

string




2、修改集合名配置文件 (已完成)

雲函數 Router目錄中修改文件 config/tableConfig.js,添加USER表輸出

// 集合名 ,表名千萬不要有空格,不然會報錯
module.exports = {
  BANNER : 'tb_banner',  //輪播表 
  THEME  : 'tb_theme', //主題表
  PRODUCT: 'tb_product', //商品信息表
  PRODUCT_THEME : 'tb_product_theme', //專題商品表
  PRODUCT_CATEGORY : 'tb_product_category', //商品分類表
  ORDER:"tb_order", //訂單表
  USER:"tb_user" //用戶表
}

3、修改集合欄位配置類(已完成)

fields 文件夾新建 userField.js

// tb_user 指定返回結果中記錄需返回的欄位
module.exports = {
  USERFIELD: {
    _id:false,   
    nickName: true,
    gender: true,
    avatarUrl:true,
    status:true
  }
}

4、業務層實現

1)、service層

用戶登錄方法,如果沒有用戶,添加記錄,如果有記錄,修改用戶登錄ip

在雲函數 service 文件夾創建 userService.js

const model = require('../models/BaseModel.js')
const { USER  } = require('../config/tableConfig.js')
// 返回欄位處理
const { USERFIELD } = require('../fields/userField.js')
/**
 * 用戶登錄方法
 * @return 
 */
const userLogin = async (ip,openId,userInfo) => { 
  //1、根據openId查找資料庫中的記錄數  
  let options={}
  options.openId= openId
  const total=await model.count(USER,options)  
 
  let current_time =(new Date()).getTime() //當前時間戳 ,毫秒 
  if (total) {
    //更新用戶信息
    let condition={}
    condition.openId=openId
    let  data={}
    data.nickName=userInfo.nickName
    data.gender=userInfo.gender
    data.avatarUrl=userInfo.avatarUrl    
    data.update_time=current_time
    data.last_login_time=current_time
    data.last_login_ip=ip
   
    await model.updatebywhere(USER,condition,data)    
  } else {
    //插入用戶數據
    let  data={}
    data.nickName=userInfo.nickName
    data.gender=userInfo.gender
    data.avatarUrl=userInfo.avatarUrl   
    data.openId=openId
    data.create_time=current_time
    data.update_time=current_time
    data.last_login_time=current_time
    data.last_login_ip=ip
    data.status=0
    data.isAdmin=0
    await model.add(USER,data)
   
  }
 //返回用戶信息
  const data= await model.query(USER,USERFIELD,options)
  return data[0]
}

/**
 * 用戶信息初始化方法,將用戶的openid值記錄到用戶表中,並返回用戶信息
 * @return 
 */
const userInit = async (ip,openId) => { 
  //1、根據openId查找資料庫中的記錄數  
  let options={}
  options.openId= openId
  const total=await model.count(USER,options)  
 
  let current_time =(new Date()).getTime() //當前時間戳 ,毫秒 
  if (total) {
    //更新用戶信息
    let condition={}
    condition.openId=openId
    let  data={}   
    data.last_login_time=current_time
    data.last_login_ip=ip
   
    await model.updatebywhere(USER,condition,data)    
  } else {
    //插入用戶數據
    let  data={}
    
    data.openId=openId
    data.nickName='' //暱稱設置為空字符串,方便以後查找授權用戶
    data.create_time=current_time
    data.update_time=current_time
    data.last_login_time=current_time
    data.last_login_ip=ip
    data.status=0
    data.isAdmin=false
    await model.add(USER,data)
   
  }
 //返回用戶信息
 const data= await model.query(USER,USERFIELD,options)
 return data[0]
}

module.exports = {
  userLogin,
  userInit  
}

2)、controller層

controller 文件夾新建 userController.js

// 返回工具類
const returnUtil = require('../utils/ReturnUtil.js')

// 用戶業務層
const userService = require('../service/userService.js')




//  用戶登錄
 function userLogin(ip,openId,userInfo){
    return async function (ctx, next) {     
      ctx.data = {} 
      const data=await userService.userLogin(ip,openId,userInfo)  // 取出數據     
      ctx.data = data
      ctx.body = await returnUtil.success(ctx)
      await next();
    }     
 } 
//  用戶信息初始化
function userInit(ip,openId){
  return async function (ctx, next) {     
    ctx.data = {} 
    const data=await userService.userInit(ip,openId)  // 取出數據     
    ctx.data = data
    ctx.body = await returnUtil.success(ctx)
    await next();
  }     
} 
module.exports = {
  userLogin,
  userInit   
}

5、入口文件

注意這裡需要傳遞openId和userInfo參數,

其中的ip來自於雲端 ,

openId來自於雲端,

userInfo來自於event.userInfo

/********************    用戶登錄   *******************************/    
app.router('user/userLogin', userController.userLogin(ip, openId,options.userInfo)); 
// 雲函數入口文件
const cloud = require('wx-server-sdk')
const TcbRouter = require('tcb-router');
const indexController = require('./controller/indexController')
const roomController = require('./controller/roomController')
const userController = require('./controller/userController')
cloud.init()


// 雲函數入口函數
exports.main = async (event, context) => {
  const app = new TcbRouter({ event });
  // app.use 表示該中間件會適用於所有的路由
  app.use(async (ctx, next) => {
    ctx.data = {};
    await next(); // 執行下一中間件
  });
  let options = {} 
  options = event.data  // event.data包含前台傳過來的參數
  //記錄用戶ip地址
  const wxContext = cloud.getWXContext();
  const ip = wxContext.CLIENTIP ? wxContext.CLIENTIP : wxContext.CLIENTIPV6
   //記錄用戶openid
  const openId=event.userInfo.openId
/***************************    首頁   *****************************************/

  app.router('index/getBanner', indexController.getBanner()) // 獲取輪播
  app.router('index/getRoom', indexController.getRoom()) //  獲取房間信息



/***************************    房間信息   *************************************/  

app.router('room/getRoomById', roomController.getRoomById(options._id)) //  獲取房間詳情信息

  
/********************    用戶登錄   *******************************/    
app.router('user/userLogin', userController.userLogin(ip, openId,options.userInfo))
app.router('user/userInit', userController.userInit(ip, openId))

/***************************    訂單   *****************************************/  


  return app.serve();
}

三、前端使用

1、封裝api_user.js

在前端 service 文件夾新建 api_user.js

import { myCloudrequest } from '../utils/cloudRequest.js'
//  用戶登錄
const userLogin=(userInfo)=>{  
   
    let data={userInfo}  //傳遞的是一個對象
  //返回的是一個promise對象 
  return myCloudRequest.request("user/userLogin",data)
}

//  用戶信息初始化
const userInit=()=>{  
   
  
//返回的是一個promise對象 
return myCloudRequest.request("user/userInit")
}
module.exports = {
 
  userLogin,
  userInit
}

2、在app.js

全局保存用戶信息,和用戶登錄狀態

// app.js
import {userInit} from '/service/api_user'

let userInfo =wx.getStorageSync("userInfo") || {} //用戶信息
let isLogin = JSON.stringify(userInfo) != "{}" //用戶登錄狀態

App({   
  
  // 引入`towxml3.0`解析方法
  towxml:require('/towxml/index'),
  onLaunch: async function () {
    if (!wx.cloud) {
      console.error('請使用 2.2.3 或以上的基礎庫以使用雲能力');
    } else {
      wx.cloud.init({
        // env 參數說明:
        //   env 參數決定接下來小程序發起的雲開發調用(wx.cloud.xxx)會默認請求到哪個雲環境的資源
        //   此處請填入環境 ID, 環境 ID 可打開雲控制台查看
        //   如不填則使用默認環境(第一個創建的環境)
        env: 'cloud1-********',
        traceUser: true,
      });
    }
    this.globalData = {     
      userInfo: userInfo,
      isLogin: isLogin,
      
    }

    //將用戶的openid值記錄到用戶表中,並返回用戶信息
    const res = await userInit()
   
    wx.setStorageSync("userInfo", res.data) //將後端返回的用戶信息保存到緩存中    
    this.globalData.userInfo = res.data  //將後端返回的用戶信息保存到app中
    
  }
});

3、在需要判斷用戶登錄的頁面

比如提交訂單頁面的提交表單方法裡面,根據app裡面的isLogin進行判斷用戶是否登錄

let app = getApp()
/**提交訂單 **/
confirm: async function () {
  //首先判斷用戶是否登錄  
  if (!app.globalData.isLogin) {
    await showModal({content:'請先登錄',showCancel:false})
    wx.switchTab({
      url: '../mine/mine',
    })   
    return 
  }
 。。。
} 



關鍵字: