微信登录流程

  1. 建立 vux store文件夹 index.js文件
import Vue from 'vue'
import Vuex from 'vuex'
import request,{PostHeader} from '@/pages/bbt_api/http.js'
Vue.use(Vuex)
// 本地存储中用户信息的 key
const USER_INFO = 'userInfo'
// 本地存储中确认订单信息的 key
const ORDER_INFO = 'orderInfo'
// 购物车信息的 key
const SHOPPING_INFO = 'shoppingCartInfo'
// 用户状态信息的 key
const USER_STATE_INFO = 'userstateinfo'
// 上级用户的id的 key
const PARENT_ID = 'parentid'
const store = new Vuex.Store({
    state: {
		// 用户信息
		userInfo: uni.getStorageSync(USER_INFO) ? JSON.parse(uni.getStorageSync(USER_INFO)) : { id: 22},
		// 确认订单信息
		orderInfo:uni.getStorageSync(ORDER_INFO) ? JSON.parse(uni.getStorageSync(ORDER_INFO)) : {},
		// 购物车订单信息
		shoppingCartInfo:uni.getStorageSync(SHOPPING_INFO) ? JSON.parse(uni.getStorageSync(SHOPPING_INFO)) : {},
		// 用户状态信息
		userStateInfo:uni.getStorageSync(USER_STATE_INFO) ? JSON.parse(uni.getStorageSync(USER_STATE_INFO)) : {},
		// 上级用户id
		parentId: uni.getStorageSync(PARENT_ID)
	},
    mutations: {
		// 更新用户信息
		updateUserInfo(state,userInfo){
			// 对数据做持久化处理
			uni.setStorageSync(USER_INFO,JSON.stringify(userInfo));
			// 更新 state 中的数据
			state.userInfo = {...state.userInfo,...userInfo}
		},
		// 更新确认订单信息
		updateOrderInfo(state,orderInfo){
			// 对数据做持久化处理
			uni.setStorageSync(ORDER_INFO,JSON.stringify(orderInfo));
			// 更新 state 中的数据
			state.orderInfo = {...state.orderInfo,...orderInfo}
		},
		// 更新购物车订单信息
		updateShoppingCartInfo(state,shoppingCartInfo){
			// 对数据做持久化处理
			uni.setStorageSync(ORDER_INFO,JSON.stringify(shoppingCartInfo));
			// 更新 state 中的数据
			state.shoppingCartInfo = {...shoppingCartInfo}
		},
		// 更新用户状态信息
		updateUserStateInfo(state,userStateInfo){
			// 对数据做持久化处理
			uni.setStorageSync(USER_STATE_INFO,JSON.stringify(userStateInfo));
			// 更新 state 中的数据
			state.userStateInfo = {...userStateInfo}
		},
		// 更新上级用户id
		updateParentId(state,parentId){
			// 如果没有上级用户的id
			if(parentId==='undefined') return uni.removeStorageSync(PARENT_ID)
			// 对数据做持久化处理
			uni.setStorageSync(PARENT_ID,parentId);
			// 更新 state 中的数据
			state.parentId = parentId
		},
		// 清空用户信息
		clearUserInfo(state){
			state.userInfo = {}
			state.userStateInfo = {}
			// 清空本地存储中的用户信息
			uni.clearStorageSync()
		}
	},
	actions:{
		// 绑定上级用户的方法
		async bindSuperiorUser(context){
			try{
				// 如果不是通过上级用户分享的小程序码进入的,则终止函数执行
				if(!context.state.parentId) return
				// 准备请求参数
				const requestPayload = {
					userid:context.state.userInfo.id,
					topid:context.state.parentId
				}
				// 发送请求
				await request('/UserResourcesWX/updateBd',PostHeader,requestPayload)
				// console.log(context)
			}catch(e){
				//TODO handle the exception
			}
		},
		// 提交上级用户的分享记录
		async submitRecords(context){
			try{
				// 如果没有绑定上级用户或者没有登录,则终止函数执行
				if(!context.state.parentId || !context.state.userInfo.id) return
				// 如果有绑定上级用户,则准备请求参数
				const requestPayload = {
					userid:context.state.userInfo.id,
					topid:context.state.parentId
				}
				// 发送请求
				await request('/UserResourcesWX/addBd',PostHeader,requestPayload)
			}catch(e){
				//TODO handle the exception
			}
		}
	}
})
export default store

登录页面代码

<template>
	<view class="Login_container" :style="'height:'+ screenHeight +'px !important;'">
		<view class="logo_box">
			<image src="../../static/login_banner.png" mode="" class="logo"></image>
		</view>
		<!-- <button class="phone_btn" open-type="getPhoneNumber" @getphonenumber="getPhoneNumber">获取手机号一键登录</button> -->
		<!-- <view class="other-login-methods_box">
			<view class="line"></view>
			<view class="other-login-methods_btn">其他登录方式</view>
			<view class="line"></view>
		</view> -->
		<button class="wx-login_box" @click="wxLogin">微信授权登录</button>
	</view>
</template>

<script>
	import {
		mapState,
		mapMutations,
		mapActions
	} from 'vuex'
	export default {
		computed: {
			...mapState(['userInfo'])
		},
		data() {
			return {
				//用户openid
				userOpenid: '',
				// 当前用户签名
				session_key: '',
				// 当前设备的可使用高度
				screenHeight: '',
				// 开关阀
				flag: true
			}
		},
		onLoad() {
			// 获取当前设备的可使用窗口高度
			this.screenHeight = uni.getSystemInfoSync().windowHeight;
			// 调用获取请求参数 code 的方法
			this.getCodeData()
		},
		// 页面卸载时触发(点击返回按钮)
		onUnload() {},
		methods: {
			...mapMutations(['updateUserInfo']),
			...mapActions(['submitRecords']),
			// 获取请求参数 code 的方法
			getCodeData() {
				// 调用微信提供的接口获取 code 
				uni.login({
					success: async (res) => {
						// 准备请求参数
						const requestPayload = {
							code: res.code
						}
						// 发送请求
						const result = await this.$request('/userLong/findOpenId', this.$PostHeader,
							requestPayload)
						// 如果请求失败,则终止函数执行
						if (result.status !== '200') return
						// 将响应的数据保存到data中
						this.userOpenid = result.data
						this.session_key = result.session_key
						// 调用 store 的方法将数据保存到 store 中,并在 store 中做持久化处理
						this.updateUserInfo({
							...this.userInfo,
							session_key: result.session_key,
							userOpenid: result.data
						})
					}
				})
			},
			// 处理函数,当手机号登录按钮被点击时触发,获取用户手机号
			async getPhoneNumber(e) {
				try {
					// 如果阀门关闭,则终止函数
					if (!this.flag) return
					// 进来后,关闭阀门,知道当前执行完毕后再开启
					this.flag = false
					// 如果用户不同意授权
					if (e.detail.errMsg === "getPhoneNumber:fail user deny") {
						// 提示用户
						uni.showToast({
							icon: "none",
							title: '请允许获取手机号,否则功能不可用!',
						})
						// 开启阀门,并终止函数执行
						return this.flag = true
					}
					// 如果用户同意授权,准备获取手机号的请求参数
					const queryInfo = {
						// 加密数据
						encryptDataB64: e.detail.encryptedData,
						// 签名
						sessionKeyB64: this.session_key,
						// 初始向量
						ivB64: e.detail.iv
					}
					// 发送请求
					const result = await this.$request('/WechatDecryptDataUtil/jmphone', this.$PostHeader, queryInfo)
					// 如果请求失败,终止函数执行
					if (result.status !== '200') return
					// 如果请求成功,拿到当前用户的手机号
					const phone = JSON.parse(result.data).phoneNumber
					// 准备手机号登录的请求参数
					const requestPayload = {
						// 当前用户手机号
						phone: phone,
						// 当前用户的 openid
						openid: this.userOpenid
					}
					// 发送请求
					const res = await this.$request('/userLong/addUer2', this.$PostHeader, requestPayload)
					// 如果请求失败,终止函数执行
					if (res.status !== '200') return
					// 如果请求成功,调用 store 的方法保存数据到 store 中,并做持久化处理
					this.updateUserInfo({
						id: result.data
					})
					// 返回之前的页面
					uni.navigateBack()
					// 开启阀门
					this.flag = true
				} catch (e) {
					// 开启阀门
					this.flag = true
					//TODO handle the exception
				}
			},
			// 微信授权登录的方法
			wxLogin() {
				try {
					// 如果阀门关闭,则终止函数
					if (!this.flag) return
					// 进来后,关闭阀门,知道当前执行完毕后再开启
					this.flag = false
					// 获取用户基本信息
					uni.getUserProfile({
						// 不写不弹提示框
						desc: '正在获取',
						// 当用户同意授权的时候触发
						success: async (res) => {
							// 调用 store 的方法将数据保存到 store 中,并在 store 中做持久化处理
							this.updateUserInfo({
								...this.userInfo,
								...res.userInfo
							})
							// 准备请求参数
							const requestPayload = {
								openid: this.userOpenid,
								...res.userInfo,
								topid: 0
							}
							// 发送请求
							const result = await this.$request('/userLong/loginUers', this.$PostHeader,
								requestPayload)
							// 如果请求失败,则终止函数执行
							if (result.status !== '200') return
							// 调用 store 的方法保存数据到 store 中,并在 store 中做持久化处理
							this.updateUserInfo({
								...this.userInfo,
								id: result.data
							})
							// 调用提交分享记录的方法
							await this.submitRecords()
							// 返回之前的页面
							uni.navigateBack()
							// 开启阀门
							this.flag = true
						},
						// 当用户拒绝授权的时候触发
						fail: () => {
							// 开启阀门
							this.flag = true
						}
					})
				} catch (e) {
					// 开启阀门
					this.flag = true
					//TODO handle the exception
				}
			},
		}
	}
</script>

<style scoped lang="scss">
	.Login_container {
		background-color: #fff;
		overflow: auto;

		// 登录图片盒子
		.logo_box {
			width: 750rpx;
			height: 252rpx;
			margin: 0 auto;
			margin-top: 220rpx;

			.logo {
				width: 100%;
				height: 100%;
			}
		}

		// 获取手机号按钮
		.phone_btn {
			width: 680rpx;
			height: 90rpx;
			color: #0B8495;
			font-size: 30rpx;
			text-align: center;
			margin: 0 auto;
			margin-top: 300rpx;
			border-radius: 45rpx;
			border: 1px solid #0B8495;
			line-height: 90rpx;
			background-color: #fff !important;
		}

		// 其它登录方式
		.other-login-methods_box {
			display: flex;
			justify-content: space-around;
			margin-top: 130rpx;

			.line {
				width: 220rpx;
				height: 2rpx;
				background-color: #F5F5F5;
			}

			.other-login-methods_btn {
				font-size: 20rpx;
				color: #999999;
				line-height: 0.2;
			}
		}

		// 微信登录盒子
		.wx-login_box {
			width: 300rpx;
			height: 90rpx;
			background-color: #fff !important;
			color: #09BB07;
			font-size: 30rpx;
			border-radius: 45rpx;
			border: 1px solid #09BB07;
			text-align: center;
			line-height: 90rpx;
			margin-top: 90rpx;
		}
	}
</style>

我的页面代码

<template>
	<view class="my_container">
		<view class="headBg_box">
			<!-- 页面标题 -->
			<view class="head_title">我的</view>
			<!-- 已登录状态 -->
			<view class="login-state_box" v-if="userInfo.id">
				<view class="left_box">
					<view class="avatar_box">
						<!-- <image :src="userInfo.avatarUrl" mode="" class="avatar"></image> -->
						<open-data type="userAvatarUrl" class="avatar"></open-data> 
					</view>
					<view class="info_box">
						<view class="name_box">
							<!-- <view class="name">{{userInfo.nickName}}</view> -->
							<open-data type="userNickName" class="name"></open-data> 
							<view class="icon_edit" v-if="userInfo.id">
								<image :src="require('../../static/icon_edit.png')" mode="" class="photo"
									@click="onServiceItemClick('user-info')"></image>
							</view>
						</view>
						<view class="level_box" v-if="userStateInfo.vips===0">普通用户</view>
						<view class="level_box" v-else-if="userStateInfo.vips===1">业务员</view>
						<view class="level_box" v-else-if="userStateInfo.vips===2">经销商</view>
					</view>
				</view>
				<!-- 成为经销商按钮 -->
				<!-- <view class="right_box" v-if="userStateInfo.vips !== 2">
					<button class="add_btn" plain :border="false"
						@click="onServiceItemClick('add-distributor')">成为经销商</button>
				</view> -->
				<!-- 二维码按钮 -->
				<view class="code_box" @click="onCodeClick" v-if="userStateInfo.vips===1 || userStateInfo.vips===2">
					<image :src="require('../../static/icon_code.png')" mode="" class="photo"></image>
					<view class="label_box">二维码</view>
				</view>
			</view>
			<!-- 未登录状态 -->
			<view class="logout-state_box" @click="onLoginClick" v-else>
				<view class="avatar_box">
					<image :src="require('../../static/default_avatar.png')" mode="" class="avatar"></image>
				</view>
				<view class="tip_box">未登录</view>
			</view>
		</view>
		<!-- 账户盒子 -->
		<view class="account_box">
			<view class="balance_box" @click="onServiceItemClick('my-balance')">
				<view class="number_box">{{userStateInfo.topupMoney}}</view>
				<view class="label_box">
					<image :src="require('../../static/icon_balance.png')" class="label_icon" mode=""></image>
					<text class="label_desc">账户余额</text>
				</view>
			</view>
			<!-- 分割线 -->
			<view class="line_box">
				<view class="line"></view>
			</view>
			<view class="balance_box" @click="onServiceItemClick('my-points')">
				<view class="number_box">{{userStateInfo.earningsMoney}}</view>
				<view class="label_box">
					<image :src="require('../../static/icon_integral.png')" class="label_icon" mode=""></image>
					<text class="label_desc">我的积分</text>
				</view>
			</view>
		</view>
		<!-- 我的服务盒子 -->
		<view class="service_box">
			<view class="head_box">
				<view class="head-title_box">我的服务</view>
			</view>
			<view class="list_box">
				<view class="list_item" @click="onServiceItemClick('my-collection')">
					<image :src="require('../../static/service_01.png')" mode="" class="photo"></image>
					<view class="label_box">我的收藏</view>
				</view>
				<view class="list_item" @click="onServiceItemClick('receiving-address')">
					<image :src="require('../../static/service_02.png')" mode="" class="photo"></image>
					<view class="label_box">收货地址</view>
				</view>
				<view class="list_item" @click="onServiceItemClick('my-comments')">
					<image :src="require('../../static/service_03.png')" mode="" class="photo"></image>
					<view class="label_box">我的评价</view>
				</view>
				<view class="list_item" @click="onServiceItemClick('my-info')">
					<image :src="require('../../static/service_04.png')" mode="" class="photo"></image>
					<view class="label_box">我的信息</view>
				</view>
				<view class="list_item" @click="onServiceItemClick('team-hotline')">
					<image :src="require('../../static/service_05.png')" mode="" class="photo"></image>
					<view class="label_box">团购热线</view>
				</view>
				<view class="list_item" @click="onServiceItemClick('resource-promotion')" v-if="userStateInfo.vips===2">
					<image :src="require('../../static/service_06.png')" mode="" class="photo"></image>
					<view class="label_box">资源推介</view>
				</view>
				<view class="list_item" @click="onServiceItemClick('my-team')"
					v-if="userStateInfo.vips===1 || userStateInfo.vips===2">
					<image :src="require('../../static/service_07.png')" mode="" class="photo"></image>
					<view class="label_box">我的团队</view>
				</view>
				<view class="list_item" @click="onServiceItemClick('about-us')">
					<image :src="require('../../static/service_08.png')" mode="" class="photo"></image>
					<view class="label_box">关于我们</view>
				</view>
			</view>
		</view>
		<!-- 二维码弹出层 -->
		<van-popup :show="isShowCodePopup" @close="onCloseCodePopup" round closeable>
			<image :src="userStateInfo.ewm" mode="" class="code-photo_box" v-if="userStateInfo.vips!==0"></image>
			<!-- <view class="code-photo_box"></view> -->
		</van-popup>
	</view>
</template>

<script>
	import {mapState,mapMutations} from 'vuex'
	export default {
		computed: {
			...mapState(['userInfo', 'userStateInfo'])
		},
		data() {
			return {
				// 控制二维码弹出层的显示与隐藏
				isShowCodePopup: false,
			}
		},
		onShow() {
			// 调用获取用户状态的方法
			this.getUserState()
		},
		methods: {
			...mapMutations(['updateUserStateInfo']),
			// 获取用户状态的方法
			async getUserState() {
				try {
					// 如果没有登录或者已经获取过用户状态,则终止函数执行
					if (!this.userInfo.id) return
					// 准备请求参数
					const requestPayload = {
						id: this.userInfo.id
					}
					// 发送请求
					const res = await this.$request('/userLong/findId', this.$PostHeader, requestPayload)
					// 如果请求失败,则终止函数执行
					if (res.status !== '200') return
					// 如果请求成功,调用 store 的 mutation
					this.updateUserStateInfo(res.data)
				} catch (e) {
					//TODO handle the exception
				}
			},
			// 处理函数,当登录按钮被点击时触发
			onLoginClick() {
				// 跳转到登录页面
				uni.navigateTo({
					url: '/pages/home/Login'
				})
			},
			// 处理函数,当服务项被点击时触发
			onServiceItemClick(address) {
				// 如果用户未登录
				if (!this.userInfo.id) {
					// 跳转到登录页面,并终止函数执行
					return uni.navigateTo({
						url: '/pages/home/Login'
					})
				}
				// 跳转到对应的页面
				uni.navigateTo({
					url: '/pages/my/' + address
				})
			},
			// 处理函数,当二维码被点击时触发
			onCodeClick() {
				// 显示二维码弹出层
				this.isShowCodePopup = true
			},
			// 处理函数,当关闭二维码弹出层时触发
			onCloseCodePopup() {
				// 隐藏二维码弹出层
				this.isShowCodePopup = false
			}
		}
	}
</script>

<style lang="scss" scoped>
	.my_container {
		// 头部容器
		.headBg_box {
			width: 750rpx;
			height: 400rpx;
			background-image: linear-gradient(45deg, #7cba3f, #a8da78);
			padding-top: 60rpx;
			box-sizing: border-box;

			.head_title {
				display: flex;
				justify-content: center;
				font-size: 34rpx;
				font-weight: bold;
				color: #FFFCF0;
				letter-spacing: 5rpx;
			}

			.login-state_box,
				{
				display: flex;
				margin-top: 52rpx;
				margin-left: 60rpx;
				justify-content: space-between;

				.left_box {
					display: flex;
					flex-wrap: wrap;

					.avatar_box {
						overflow: hidden;
						margin-right: 19rpx;
						width: 100rpx;
						height: 100rpx;
						border-radius: 50%;
						.avatar {
							width: 100%;
							height: 100%;
						}
					}

					.info_box {
						display: flex;
						flex-direction: column;

						.name_box {
							margin-bottom: 10rpx;
							font-size: 34rpx;
							font-weight: bold;
							color: #FFFCF0;
							margin-left: 10rpx;
							display: flex;

							.name {
								margin-right: 33rpx;
							}

							.icon_edit {
								width: 26rpx;
								height: 26rpx;

								.photo {
									width: 100%;
									height: 100%;
								}
							}
						}

						.level_box {
							width: 165rpx;
							height: 50rpx;
							background: url('~@/static/icon_level.png') no-repeat;
							background-size: 100% 100%;
							display: flex;
							align-items: center;
							padding-left: 55rpx;
							box-sizing: border-box;

							font-size: 24rpx;
							font-weight: 400;
							color: #FFFFFF;
						}
					}
				}

				.right_box {
					margin: 20rpx;
					width: 160rpx;
					height: 60rpx;
					border: 1rpx solid #fff;
					border-radius: 35rpx;
					display: flex;
					justify-content: center;
					align-items: center;

					.add_btn {
						display: flex;
						justify-content: center;
						align-items: center;
						font-size: 20rpx;
						font-weight: 400;
						color: #fff;
						border: none;
					}
				}

				.code_box {
					display: flex;
					flex-direction: column;
					align-items: center;
					margin-right: 47rpx;

					.photo {
						width: 65rpx;
						height: 57rpx;
					}

					.label_box {
						padding-top: 8rpx;
						font-size: 24rpx;
						font-weight: bold;
						color: #FFFFFF;
					}
				}
			}

			.logout-state_box {
				margin-top: 53rpx;
				margin-left: 60rpx;
				font-size: 34rpx;
				font-weight: bold;
				color: #FFFCF0;
				display: flex;

				.avatar_box {
					margin-right: 19rpx;
					width: 100rpx;
					height: 100rpx;

					.avatar {
						width: 100%;
						height: 100%;
						border-radius: 50%;
					}
				}

				.info_box {
					display: flex;
					flex-direction: column;

					.name_box {
						margin-bottom: 10rpx;
						font-size: 34rpx;
						font-weight: bold;
						color: #FFFCF0;
						margin-left: 10rpx;
						display: flex;

						.name {
							margin-right: 33rpx;
						}

						.icon_edit {
							width: 26rpx;
							height: 26rpx;

							.photo {
								width: 100%;
								height: 100%;
							}
						}
					}

					.level_box {
						width: 165rpx;
						height: 50rpx;
						background: url('~@/static/icon_level.png') no-repeat;
						background-size: 100% 100%;
						display: flex;
						align-items: center;
						padding-left: 55rpx;
						box-sizing: border-box;

						font-size: 24rpx;
						font-weight: 400;
						color: #FFFFFF;
					}
				}

				.tip_box {
					margin-top: 10rpx;
					font-size: 50rpx;
					font-weight: bold;
					color: #ddd;
				}
			}
		}

		// 账户盒子
		.account_box {
			width: 710rpx;
			height: 148rpx;
			background: #FFFFFF;
			margin: -72rpx 20rpx 0;
			border-radius: 10px;
			display: flex;
			justify-content: space-between;
			padding: 0 115rpx;
			box-sizing: border-box;
			box-shadow: 8rpx 12rpx 10rpx rgba(0, 0, 0, 0.3);

			.balance_box {
				display: flex;
				flex-direction: column;
				align-items: center;
				justify-content: space-between;

				.number_box {
					margin-top: 30rpx;
				}

				.label_box {
					margin-bottom: 27rpx;
					display: flex;
					align-items: center;

					.label_icon {
						width: 34rpx;
						height: 29rpx;
						margin-right: 10rpx;
					}

					.label_desc {
						font-size: 24rpx;
						font-weight: 400;
						color: #333333;
						opacity: 0.8;
					}
				}
			}

			.line_box {
				display: flex;
				align-items: center;
				height: 100%;

				.line {
					width: 2rpx;
					height: 43rpx;
					background: #F0F0F0;
				}
			}
		}

		// 服务盒子
		.service_box {
			margin: 25rpx;
			display: flex;
			flex-direction: column;
			width: 710rpx;
			// height: 480rpx;
			background: #FFFFFF;
			border-radius: 10px;
			box-shadow: 8rpx 12rpx 10rpx rgba(0, 0, 0, 0.3);

			.head_box {
				display: flex;
				justify-content: center;

				.head-title_box {
					padding: 40rpx 0 16rpx;
					width: 690rpx;
					border-bottom: 2rpx solid #F5F5F5;
					font-size: 28rpx;
					font-weight: 400;
					color: #333333;
				}
			}

			.list_box {
				display: flex;
				flex-wrap: wrap;


				.list_item {
					flex: 25% 0;
					display: flex;
					flex-direction: column;
					align-items: center;

					.photo {
						margin-top: 34rpx;
						margin-bottom: 20rpx;
						width: 75rpx;
						height: 75rpx;
						border-radius: 50%;
					}

					.label_box {
						margin-bottom: 60rpx;
						font-size: 24rpx;
						font-weight: 400;
						color: #333333;
					}
				}
			}
		}

		// 二维码弹出层
		.code-photo_box {
			margin: 80rpx 50rpx 50rpx;
			width: 400rpx;
			height: 400rpx;
			// background-color: skyblue;
			// .
		}

		// 补丁样式(完成后的修修补补)
		.mt_22 {
			margin-top: 22rpx;
		}
	}
</style>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值