注意:JS中对接的接口需要更换为自己业务的接口、返回值也可能不同,此示例只是提供一个思路
微信小程序 登录
功能包括
- 新用户授权登录
- 老用户自动登录
效果
- 自动登录功能:进入登录页自动执行一次登录的静默操作:如果是新用户则没有任何效果,如果是老用户则自动登录
- 进行静默登录后可以判断是否是新/老用户,进而让按钮的文本发生变化(登录/注册)
- 没有勾选协议的时候点击登录/注册按钮会自动弹出询问弹窗
代码
<template>
<myNavbar type="2" title="登录" bgColor="transparent"></myNavbar>
<image
class="bgi-box"
src="https://douleoss.oss-cn-shenzhen.aliyuncs.com/test/66275d53100d849cce5caae0.png"
mode=""
/>
<div class="login-box">
<text>{{ isRegister ? '注册' : '登录' }}</text>
<button
v-if="isAgree && isRegister"
class="login-btn"
open-type="getPhoneNumber"
@getphonenumber="register"
></button>
<button v-if="isAgree && !isRegister" class="login-btn" @click="autoLogin"></button>
<button v-if="!isAgree" class="login-btn" @click="popupShow = true"></button>
</div>
<div class="agreement-box" @click="isAgree = !isAgree">
<div class="select" :style="{ backgroundColor: isAgree ? '#eed25f' : '#fff' }">
<u-icon name="checkbox-mark" color="#666666" size="28" v-if="isAgree"></u-icon>
</div>
<div class="text">
我已阅读并同意
<text @click.stop="goAgreement">用户协议</text>
和
<text @click.stop="goAgreement">隐私权条款</text>
</div>
</div>
<u-popup :show="popupShow" @close="popupShow = false" :customStyle="{ padding: '20rpx 40rpx' }">
<div class="popup-box">
<div class="popup-title">用户协议和服务条款</div>
<div class="popup-content"
>在您注册/登录都乐导乐账号的过程,您需要阅读并同意《用户协议》和《服务条款》</div
>
<div class="popup-bottom">
<div class="cancellation" @click="popupShow = false">取消</div>
<div class="determine" v-if="isRegister">
<text>同意</text>
<button class="login-btn" open-type="getPhoneNumber" @getphonenumber="register"></button>
</div>
<div class="determine" v-else @click="autoLogin">
<text>同意</text>
</div>
</div>
</div>
</u-popup>
</template>
<script setup>
import { ref, onMounted, computed, watchEffect, getCurrentInstance } from 'vue';
import { onLoad, onUnload } from '@dcloudio/uni-app';
const { proxy } = getCurrentInstance();
const example = proxy;
import { $mini_user_phone, $mini_user_login } from '@/api';
onMounted(() => {
autoLogin();
});
onUnload(() => {
uni.removeStorageSync('registerToken');
});
let isRegister = ref(false); // 是否是注册
// 自动登录
function autoLogin() {
uni.login({
provider: 'weixin', // 使用微信登录
success: async function (loginRes) {
uni.showLoading({ title: '登录中...', mask: true });
let code = loginRes.code;
console.log('一键登录code', code);
try {
let res = await $mini_user_login({ code });
uni.hideLoading();
loginSuccess(res);
} catch (error) {
console.log(error);
uni.hideLoading();
if (error.statusCode == 407) {
uni.setStorageSync('registerToken', error.errMsg);
isRegister.value = true;
} else {
uni.showToast({ title: error.errMsg, icon: 'none' });
}
}
},
});
}
let isAgree = ref(false); // 是否同意协议
// 点击跳转协议
function goAgreement() {
console.log('跳转协议');
}
let popupShow = ref(false); // 弹窗是否显示
// 注册(手机号注册)
async function register(e) {
uni.showLoading({ title: '注册中...', mask: true });
let detail = e.detail;
console.log('手机号code', detail.code);
if (detail.errMsg !== 'getPhoneNumber:ok') {
uni.hideLoading();
return;
}
try {
let res = await $mini_user_phone({ code: detail.code });
console.log('注册成功', res);
uni.hideLoading();
loginSuccess(res, true);
} catch (error) {
console.log(error);
uni.hideLoading();
uni.showToast({ title: error.errMsg, icon: 'none' });
}
}
// 登录/注册成功
function loginSuccess(data, isRegister = false) {
isAgree.value = true;
popupShow.value = false;
uni.showToast({
title: isRegister ? '注册成功' : '登录成功',
icon: 'none',
mask: true,
duration: 1500,
});
uni.setStorageSync('token', data.token);
uni.setStorageSync('userInfo', data);
setTimeout(() => {
let path = uni.getStorageSync('path');
if (isRegister && !path) {
uni.showToast({ title: '建议先完善个人资料', icon: 'none', mask: true, duration: 1500 });
setTimeout(() => {
uni.reLaunch({ url: '/page_user/personalData' });
}, 1500);
} else {
if (path) {
uni.removeStorageSync('path');
uni.reLaunch({ url: path });
} else {
uni.reLaunch({
url: '/pages/home/index',
});
}
}
}, 1500);
}
</script>
<style lang="scss" scoped>
.bgi-box {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: -1;
}
.login-box {
width: 80%;
height: 100rpx;
background: #fdd100;
border-radius: 60rpx;
margin: 23rpx auto;
margin-top: 800rpx;
@extend %c-box-center;
font-weight: bold;
font-size: 32rpx;
color: #ffffff;
position: relative;
}
.login-btn {
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
opacity: 0;
}
.agreement-box {
width: 80%;
height: 100rpx;
margin: 0 auto;
background: #666666;
border-radius: 48rpx;
@extend %c-box-center;
.select {
width: 37rpx;
height: 37rpx;
border-radius: 50%;
margin-right: 25rpx;
@extend %c-box-center;
}
.text {
font-weight: 500;
font-size: 24rpx;
color: #ffffff;
text {
position: relative;
::before {
content: '';
width: 100%;
height: 2rpx;
background: #d2d2d2;
position: absolute;
bottom: -10rpx;
}
}
}
}
.popup-box {
.popup-title {
margin: 20rpx 0;
display: flex;
justify-content: center;
align-items: center;
font-size: 34rpx;
font-weight: 700;
}
.popup-content {
margin-bottom: 20rpx;
font-size: 24rpx;
color: #666666;
}
.popup-bottom {
display: flex;
justify-content: space-between;
align-items: center;
.determine,
.cancellation {
width: 48%;
height: 80rpx;
border-radius: 48rpx;
display: flex;
justify-content: center;
align-items: center;
font-size: 34rpx;
font-weight: 700;
color: #ffffff;
}
.determine {
background: #fdd100;
position: relative;
}
.cancellation {
background: #666666;
}
}
}
</style>
微信小程序登录(简便版)
- 没有自动登录功能
- 没有勾选协议的时候点击登录/注册按钮会自动弹出询问弹窗
- 只是简简单单的点击登录按钮进行手机号登录
代码
<template>
<div class="uni-page-box" :style="{ paddingBottom: $safeAreaBottomHeight + 'px' }">
<div class="title"> 配料查查 </div>
<div class="logo">
<image src="/static/images/logo.png" mode="scaleToFill" />
</div>
<div class="btn">
<text>登录</text>
<button open-type="getPhoneNumber" @getphonenumber="login" class="login-btn"></button>
</div>
</div>
</template>
<script setup>
import { ref, onMounted, computed, watchEffect, getCurrentInstance } from 'vue';
import { onLoad } from '@dcloudio/uni-app';
const { proxy } = getCurrentInstance();
let code = '';
onMounted(() => {});
onLoad((res) => {
uni.login({
provider: 'weixin',
success: async function (loginRes) {
console.log('uni.login API调用成功', loginRes);
code = loginRes.code;
},
fail: function (err) {
console.log('uni.login API调用失败', err);
uni.hideLoading();
},
});
});
async function login(e) {
console.log('获取手机号信息', e);
if (e.detail.errMsg != 'getPhoneNumber:ok') {
uni.showToast({
title: '获取手机号失败',
icon: 'none',
});
return;
}
uni.showLoading({
title: '登录中...',
mask: true,
});
let iv = e.detail.iv;
let encryptedData = e.detail.encryptedData;
try {
let params = {
code: code,
iv: iv,
encryptedData: encryptedData,
};
console.log('登录参数', params);
// return;
// const res = await $login(params);
// console.log('登录成功', res);
// uni.setStorageSync('token', res.token);
// uni.setStorageSync('userInfo', res);
uni.showToast({
title: '登录成功',
icon: 'success',
duration: 1500,
});
await new Promise((resolve) => setTimeout(resolve, 1500));
let path = uni.getStorageSync('path');
if (path) {
uni.removeStorageSync('path');
uni.reLaunch({
url: path,
});
} else {
uni.reLaunch({
url: '/pages/home/index',
});
}
} catch (error) {
console.log('登录失败', error);
uni.hideLoading();
}
}
function devLogin() {
uni.showModal({
title: '提示',
content: '',
placeholderText: '请输入手机号',
editable: true,
showCancel: true,
success: async ({ confirm, cancel, content }) => {
if (confirm) {
try {
// const res = await $devLogin({
// mobile: content,
// });
// console.log('登录成功', res);
// uni.setStorageSync('token', res.token);
// uni.setStorageSync('userInfo', res);
uni.showToast({
title: '登录成功',
icon: 'success',
duration: 1500,
});
await new Promise((resolve) => setTimeout(resolve, 1500));
let path = uni.getStorageSync('path');
if (path) {
uni.removeStorageSync('path');
uni.reLaunch({
url: path,
});
} else {
uni.reLaunch({
url: '/pages/home/index',
});
}
} catch (error) {
console.log('登录失败', error);
}
}
},
});
}
</script>
<style lang="scss" scoped>
.title {
font-size: 40rpx;
font-weight: bold;
text-align: center;
margin-top: 160rpx;
}
.logo {
margin-top: 60rpx;
display: flex;
justify-content: center;
image {
width: 100rpx;
height: 100rpx;
}
}
.btn {
margin: 0 auto;
margin-top: 60rpx;
width: 80%;
height: 90rpx;
background: #e94747;
border-radius: 12rpx 12rpx 12rpx 12rpx;
display: flex;
justify-content: center;
align-items: center;
font-size: 32rpx;
color: #ffffff;
font-weight: bold;
position: relative;
.login-btn {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0;
}
}
</style>
微信公众号H5 登录
注意事项以及开发参考:developers.weixin.qq.com/doc/offiacc…
代码
<template>
<div class="login-container">
<div v-if="loading" class="loading"> 登录中... </div>
<div v-else class="loading"> 授权中... </div>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue';
import { onLoad } from '@dcloudio/uni-app';
const loading = ref(false);
const appid = 'your_appid'; // 需要替换成你的公众号appid
// 获取当前页面完整URL
const getCurrentPageUrl = () => {
const pages = getCurrentPages();
const currentPage = pages[pages.length - 1];
const url = currentPage.$page.fullPath;
return `${window.location.origin}${url}`;
};
// 微信授权登录
const wxLogin = () => {
const redirectUri = encodeURIComponent(getCurrentPageUrl());
console.log('授权后重定向的回调链接地址', redirectUri);
const authUrl = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appid}&redirect_uri=${redirectUri}&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect`;
window.location.href = authUrl;
};
// 使用code获取用户信息并登录
const loginWithCode = async (code) => {
try {
loading.value = true;
// 调用后端登录接口
// let res = await $test({ code });
// uni.setStorageSync('token', '1234567890');
// uni.setStorageSync('userInfo', {
// nickName: '张三',
// avatarUrl: 'https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png',
// });
uni.showToast({
title: '登录成功',
icon: 'none',
});
setTimeout(() => {
uni.reLaunch({
url: '/pages/home/index',
});
}, 1500);
} catch (error) {
uni.showToast({
title: '登录失败',
icon: 'none',
});
} finally {
loading.value = false;
}
};
// 检查登录状态
const checkLogin = () => {
const token = uni.getStorageSync('token');
if (token) {
// 已登录,跳转到首页
uni.reLaunch({
url: '/pages/home/index',
});
return true;
}
return false;
};
onLoad((options) => {
// 如果已登录,直接跳转
if (checkLogin()) return;
// 获取url中的code参数
const code = options.code;
if (code) {
// 有code,进行登录
loginWithCode(code);
} else {
// 没有code,进行微信授权
wxLogin();
}
});
</script>
<style lang="scss" scoped>
.login-container {
width: 100%;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
.loading {
font-size: 28rpx;
color: #666;
}
}
</style>