uniapp 微信小程序封装全局弹框(登录拦截)
新增组件页面: loginProp.vue
<template>
<view class="login-box" v-if="loginShow">
<view class="center-box">
<image class="logo" src="../../static/images/logo.png"></image>
<view class="close" @tap="closeLogin">
<u-icon name='close' color="#bebebe" size="26"></u-icon>
</view>
<view class="title">登录即可体验完整功能</view>
<view class="btn-group">
<view class="invite-specia" @tap="goLogin">
<u-icon name="weixin-fill" color="#fff" size="30"></u-icon>
<view style="margin-left: 20rpx;">
微信用户一键登录
</view>
</view>
</view>
</view>
<uni-popup ref="popup">
<view class="login_phone_box">
<view class="check_box">
<u-radio-group v-model="currentCheck" placement="row">
<u-radio :customStyle="{marginRight: '8px'}" v-for="(item, index) in radiolist" :key="index"
activeColor="#fc742a" :label="item.name" :name="item.value" @change="radioChange">
</u-radio>
</u-radio-group>
</view>
<view class="title">为了验证用户登录信息,小程序将获取您的手机号</view>
<view class="operate">
<button class="login" open-type="getPhoneNumber" @getphonenumber="getPhoneNumber">登录</button>
</view>
</view>
</uni-popup>
</view>
</template>
<script>
export default {
name: 'login',
props: ['loginShow'],
data() {
return {
show: this.loginShow,
sessionKey: {},
wxCode: ''
}
},
mounted() {},
methods: {
closeLogin() {
this.$emit('closeLogin', this.show);
},
goLogin() {
let _this = this;
uni.login({
provider: "weixin",
success: (res) => {
// console.log('获取code', res);
if (res.errMsg.indexOf("ok") != -1) {
this.wxCode = res.code;
uni.showModal({
title: '温馨提示',
content: '亲,授权微信登录后才能正常使用小程序功能',
success(res) {
//如果用户点击了确定按钮
if (res.confirm) {
uni.getUserProfile({
desc: '获取你的昵称、头像、地区及性别',
success: (res) => {
// console.log('获取code', res);
let _res = _this.$myRequset({
url: "api?operate=normal.user.WxDecode",
method: "POST",
data: {
code: _this.wxCode,
encryptedData: res
.encryptedData,
iv: res.iv,
signature: res
.signature,
rawData: res.rawData
},
}).then((res) => {
_this.sessionKey = res.data
.data;
});
_this.$refs.popup.open();
_this.getPhoneNumber();
},
fail: res => {
console.log('fail', res);
//拒绝授权
uni.showToast({
title: '您拒绝了请求,不能正常使用小程序',
icon: 'none',
duration: 2000
});
return;
}
});
} else if (res.cancel) {
//如果用户点击了取消按钮
// console.log(3);
uni.showToast({
title: '您拒绝了请求,不能正常使用小程序',
icon: 'error',
duration: 2000
});
uni.switchTab({
url: "../index/index"
});
return;
}
}
});
}
}
});
},
/* 用户授权手机号 */
async getPhoneNumber(e) {
let _this = this;
try {
let _msg = e.detail.errMsg;
if (_msg == "getPhoneNumber:ok") {
// 获取手机号
_this.$refs.popup.close();
_this.isLogin = true;
let _param = {
encryptedData: e.detail.encryptedData,
iv: e.detail.iv,
sessionKey: this.sessionKey.session_key,
openid: this.sessionKey.openid,
avatarUrl: this.sessionKey.avatarUrl,
nickName: this.sessionKey.nickName,
gender: this.sessionKey.gender,
login_type: this.currentCheck // 登录类型
}
let _url = $requestApi.get_phone;
console.log('$requestApi', _url);
this.$myRequset({
url: _url,
method: "POST",
data: _param,
}).then((res) => {
if (res.data.code == 1) {
uni.showLoading({
title: '正在登录...'
});
_this.updateUserInfo(res.data.data);
} else {
uni.showToast({
title: '登录失败',
icon: 'error',
duration: 2000
});
}
}).catch((err) => {
uni.showToast({
title: '登录请求失败',
icon: 'error',
duration: 2000
});
console.log("request_err", err);
});
} else {
// 重新要求授权
}
} catch {}
},
//更新用户信息
updateUserInfo(_token) {
this.$myRequset({
url: "api?operate=normal.user.user_info",
method: "POST",
data: {
token: _token
}
}).then((_res) => {
uni.showLoading({
title: '正在登录...',
icon: 'loading'
});
if (_res.data.code == 1) {
let userInfo = _res.data.data;
uni.setStorageSync('userInfo', userInfo);
setTimeout(function() { let pages = getCurrentPages(); //获取所有页面的数组对象 console.log('pages',pages); let currPage = pages[pages.length - 1]; //当前页面 currPage.onLoad(currPage.options); // 传入参数刷新当前页面 currPage.onShow(); currPage.onReady(); /* uni.reLaunch({ // 此方法不可行,当需要登录的页面带有参数时,relaunch会跳转首页,并不会重载当前页面 url: currPage.$page.fullPath }); */ }, 1000);
} else {
uni.showToast({
title: _res.data.msg,
icon: "success",
});
}
}).catch((err) => {
console.log("request_err", err);
});
},
}
}
</script>
<style scoped lang='scss'>
.login-box {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background: rgba(0, 0, 0, 0.5);
z-index: 9999;
& .center-box {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 622rpx;
padding: 60rpx 32rpx;
border-radius: 16rpx;
opacity: 1;
background: rgba(255, 255, 255, 1);
.logo {
position: absolute;
top: -24rpx;
left: 50%;
transform: translateX(-50%);
width: 90rpx;
height: 100rpx;
}
.close {
position: absolute;
top: 24rpx;
right: 24rpx;
width: 48rpx;
height: 48rpx;
}
.title {
margin: 66rpx 0 40rpx;
text-align: center;
color: rgba(0, 0, 0, 1);
font-size: 36rpx;
font-weight: 500;
font-family: "PingFang SC";
letter-spacing: 0.6rpx;
}
.content {
margin: 40rpx 0;
font-size: 30rpx;
font-family: "PingFang SC";
letter-spacing: 0.6rpx;
color: #212121;
text-align: center;
text {
font-size: 32rpx;
letter-spacing: 0.6rpx;
color: rgba(69, 108, 255, 1);
}
}
.btn-group {
display: flex;
justify-content: center;
padding: 0 16rpx;
.invite-specia {
display: flex;
align-items: center;
justify-content: center;
width: 526rpx;
height: 88rpx;
line-height: 88rpx;
border-radius: 16rpx;
text-align: center;
background: linear-gradient(-46.8deg, #34aa3a 0%, #2d9432 100%);
color: #fff;
}
}
}
}
/* 获取手机号 */
.login_phone_box {
padding: 40rpx 30rpx 80rpx;
background-color: #fff;
border-radius: 12rpx;
width: 75%;
margin: 0 auto;
& .title {
font-size: 34rpx;
color: #7d7d7d;
margin: 0;
margin-bottom: 60rpx;
letter-spacing: unset;
}
& .operate {
display: flex;
}
& button {
border: none;
font-size: 32rpx;
color: #000;
background-color: #f5f5f5;
border-radius: 8rpx;
width: 200rpx;
padding: 0;
height: 80rpx;
line-height: 80rpx;
border-color: transparent;
outline: unset;
&.login {
background-color: #fc742a;
color: #fff;
}
}
}
</style>
页面使用:先引入组件,当组件来使用(loginShow决定啥时候显示,啥时候隐藏)
<template>
<view class="pages">
<view>
<view class="top">
<view class="flex">
<image :src="userInfo.avatar" v-if="userInfo"></image>
<image v-else src="../../static/images/default.png"></image>
<view class="flex_cloumn" v-if="userInfo">
<text class="title">{{userInfo.name}}</text>
</view>
<view v-else @tap="goLogin">
<u--text text="登录" size="18"></u--text>
</view>
</view>
</view>
<view class="bottom">
<view class="tab_box">
<view class="item" @tap="goPage('info')">
<text class="title">编辑资料</text>
<u-icon name="arrow-right" size="24"></u-icon>
</view>
</view>
</view>
<view class="operate_box" v-if="userInfo">
<button @tap="toLogout">退出登录</button>
</view>
</view>
<loginProp :loginShow="loginShow" @closeLogin="closeLogin"></loginProp>
</view>
</template>
<script>
import loginProp from "../../components/login/loginProp.vue";
export default {
name: "personal",
components: {
loginProp
},
data() {
return {
loginShow:false, //登录弹框
userInfo: {}
}
},
onShow() {
this.userInfo = this.checkLogin();
console.log('userInfo', this.userInfo);
},
onPullDownRefresh() {
},
onLoad() {
this.initData();
},
methods: {
closeLogin(){
this.loginShow = false;
},
/* 初始化页面数据 */
initData() {
},
/* 修改排序 */
changeSort(_index) {
this.currentSort = _index;
this.$refs.popup_sort.open();
},
/* 修改在线状态 */
goPage(_type) {
let _url = '';
switch (_type) {
case 'info': // 编辑资料
_url = "../../pageA/myDetail/myDetail";
break;
}
uni.navigateTo({
url:_url
})
},
goLogin(){
this.loginShow = true;
},
/* 快速进去会话 */
changeChatin() {},
toLogout() {
let _this = this;
let context = {
loading_title: "正在退出...",
content: "确定退出登录吗?",
cancel: "取消退出"
};
uni.showModal({
title: '温馨提示',
content: context.content,
success: (res) => {
if (res.confirm) {
_this.$myRequset({
url: this.$requestApi.logout,
data: {
token: _this.userInfo.token
}
}).then((res) => {
if (res.data.code == 1) {
uni.showLoading({
title: context.loading_title
});
setTimeout(function() {
uni.removeStorageSync('userInfo');
uni.reLaunch({
url: "../index/index"
});
uni.showToast({
title: res.data.msg,
icon: "none"
});
uni.hideLoading();
}, 2000);
} else {
uni.showToast({
title: res.data.msg,
icon: "error"
});
}
}).catch((err) => {
console.log("request_err", err);
});
} else if (res.cancel) {
uni.showToast({
title: context.cancel,
icon: "none"
})
}
}
})
}
}
}
</script>
<style lang="scss">
@import url("personal.css");
</style>
这个只能说是使用公共组件的方式了,网上有解决方案,是使用dom挂载全局的方式,但是不能使用正常js追加dom元素的方式,小程序不支持document.appensChild的方式。
具体实现方式请查看: https://blog.csdn.net/jsmeng626/article/details/125338447,这个方式是没办法全局挂载的,目前我没找到解决方案。。。如果有大佬能有更好的解决方案麻烦评论区告知下哦,互相交流,谢谢!
本文来自博客园,作者:小虾米吖~,转载请注明原文链接:https://www.cnblogs.com/LindaBlog/p/16636134.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」