具体流程:
进入 h5 ➡️ 静默登录 ➡️ 请求登录接口 ➡️ 必要时候调起登录组件 ➡️ 点击按钮进行非静默登录 ➡️ 再次请求登录接口 ➡️ 获取到所有用户数据
一、封装登录 function
authLogin: (callback) => {
const that = this;
// 判断是否是在微信环境下运行
if (utils.isWechat()) {
const token = window.localStorage.getItem('__token');
const unionid = window.localStorage.getItem('__unionid');
const loginType = window.localStorage.getItem('__loginType');
// 有token证明登录过,可直接进行回调
if (token) {
callback();
return;
}
if (!unionid) {
// 判断登录方式为静默或非静默, snsapi_base 静默,snsapi_userinfo 非静默
const snsapi = loginType == "snsapi_userinfo" ? "snsapi_userinfo" : "snsapi_base";
// 获取 code 方法,附文章最下边
let _code = utils.getUrlParam("code");
if (_code == null || _code === "") {
// 进行微信授权,附文章最下边
// 传当前页面的URL(微信授权完之后返回到的页面)和 登录方式
utils.getWXCode(window.location.href, snsapi);
} else {
uni.request({
url: '登录请求接口',
method: "GET",
data: {
code: _code,
snsapi: snsapi
},
success: (res) => {
// 静默登录获取到的 unionid 为假数据,我这里后端接口设置静默登录时候返回为 "" ,方便后面判断是否需要非静默登录
window.localStorage.setItem('__unionid', res.data.data.unionid);
window.localStorage.setItem('__token', res.data.data.token);
window.localStorage.setItem('__openid', res.data.data.openid);
window.localStorage.removeItem('__loginType');
// 登录成功后的回调,我这里的每个接口请求都需要在有token的前提下进行
callback();
},
fail: (err) => {
// alert("err");
uni.hideLoading();
uni.showToast({
title: '登录失败'
})
},
})
}
}
} else {
uni.showModal({
title: '错误提示',
content: '请在微信客户端打开链接',
showCancel: false,
success(res) {
if (res.confirm) {}
}
})
}
},
二、封装非静默登录组件
<template>
<view class="login-container">
<view class="login-close" @click="closeLogin"></view>
<view class="login-main">
<view class="close-btn">
<image class="" src="../../static/icon/close3.png" mode="widthFix" @click="closeLogin"></image>
</view>
<view class="logo">
<image src="../../static/img/logo.png" mode="widthFix"></image>
</view>
<view class="txt">登陆后体验完整功能哦!</view>
<button class="login-btn" @click="login">微信登录</button>
</view>
</view>
</template>
<script>
import utils from '../../utils/utils.js';
export default {
data() {
return {}
},
props: ['page'],
onLoad() {},
methods: {
login() {
// 非静默登录前先把token缓存清除,否则授权完之后跳转过去不会请求登录接口
window.localStorage.removeItem('__token');
// 设为非静默
window.localStorage.setItem('__loginType', 'snsapi_userinfo');
utils.getWXCode(this.page, 'snsapi_userinfo');
},
closeLogin() {
this.$emit('closeLogin', false);
}
}
}
</script>
<style lang="less" scoped>
.login-container {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background-color: rgba(0, 0, 0, 0.6);
z-index: 99;
.login-close {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: calc(100% - 630rpx);
}
.login-main {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
height: 630rpx;
background-color: #fff;
border-radius: 16rpx 16rpx 0 0;
.close-btn {
display: flex;
align-items: center;
justify-content: flex-end;
padding: 30rpx 30rpx 0;
// position: absolute;
// top: 30rpx;
// right: 30rpx;
image {
width: 40rpx;
height: 40rpx;
}
}
.logo {
display: flex;
align-items: center;
justify-content: center;
image {
width: 170rpx;
height: 170rpx;
}
}
.txt {
margin-top: 40rpx;
font-weight: 500;
font-size: 36rpx;
color: #333333;
text-align: center;
}
.login-btn {
margin: 96rpx 30rpx 0;
color: #fff;
background-color: #49C265;
}
}
}
</style>
三、使用组件
<template>
<view class="content">
<!-- 登录组件 -->
<loginMask v-if="showLogin" :page="myPage" @closeLogin="closeLogin"></loginMask>
</view>
</template>
<script>
import utils from '../../utils/utils.js';
import loginMask from '../../components/login/login.vue';
export default {
data() {
return {
showLogin: false,
myPage: '当前页面的链接,不能使用 window.location.href,防止携带code',
}
},
components: {
loginMask
},
onLoad() {
const that = this;
// 调用封装好的登录function
// 登录function封装好后可以放在 Vue.prototype 上,直接this.authLogin调用
// 也可以放在utils.js中,用utils.authLogin调用
that.authLogin(() => {
that.goodsList();
})
},
methods: {
goodsList() {
const that = this;
uni.request({
url:"请求接口"
})
},
closeLogin(e) {
this.showLogin = e;
},
// 在需要展示登录组件的时候让 this.showLogin = true
}
}
</script>
<style lang="less" scoped></style>
四、utils/utils.js
export default {
// 判断是否为微信环境
isWechat: () => {
var ua = navigator.userAgent.toLowerCase();
var isWXWork = ua.match(/wxwork/i) == 'wxwork';
var isWeixin = !isWXWork && ua.match(/MicroMessenger/i) == 'micromessenger';
return isWeixin;
},
// 获取code并登录
getWXCode: async (url, snsapi) => {
let appid = '' //公众号的唯一标识
let local = encodeURIComponent(url); //授权后重定向的回调链接地址
let time = +new Date(); //时间戳
window.location.href =
`https://open.weixin.qq.com/connect/oauth2/authorize?
appid=${appid}&
redirect_uri=${local}&
response_type=code&
scope=${snsapi}&
state=1&
time=${time}#wechat_redirect`;
},
// 截取code
getUrlParam: (name) => {
let reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
let r = window.location.search.substr(1).match(reg);
if (r != null) {
return unescape(r[2]);
}
return null;
},
}