uni-quick-login.vue 10.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12
<template>
	<view>
		<view class="quick-login-box">
			<view class="item" v-for="(item,index) in servicesList" :key="index"
				@click="item.path?to(item.path):login_before(item.id,false)">
				<image class="logo" :src="item.logo" mode="widthFix"></image>
				<text class="login-title">{{item.text}}</text>
			</view>
		</view>
		<!-- #ifdef MP-WEIXIN -->
		<uni-user-profile @next="doUserProfileNext" ref="userProfile"></uni-user-profile>
		<!-- #endif -->
13 14 15 16 17 18 19
	</view>
</template>
<script>
	import {
		mapGetters,
		mapMutations
	} from 'vuex';
DCloud_JSON's avatar
DCloud_JSON 已提交
20
	//前一个窗口的页面地址。控制点击切换快捷登录方式是创建还是返回
21
	import loginSuccess from '@/pages/ucenter/login-page/common/loginSuccess.js';
22 23
	const db = uniCloud.database();
	const usersTable = db.collection('uni-id-users')
24
	export default {
DCloud_JSON's avatar
DCloud_JSON 已提交
25 26 27
		computed: {
			loginConfig() {
				return getApp().globalData.config.router.login
28 29 30
			},
			agreements() {
				return getApp().globalData.config.about.agreements || []
DCloud_JSON's avatar
DCloud_JSON 已提交
31 32
			}
		},
33 34 35
		data() {
			return {
				servicesList: [{
DCloud_JSON's avatar
DCloud_JSON 已提交
36
						"id": "username",
DCloud_JSON's avatar
DCloud_JSON 已提交
37
						"text": "账号登录",
38 39 40 41
						"logo": "/static/uni-quick-login/user.png",
						"path": "/pages/ucenter/login-page/pwd-login/pwd-login"
					},
					{
DCloud_JSON's avatar
DCloud_JSON 已提交
42
						"id": "smsCode",
43 44
						"text": "短信验证码",
						"logo": "/static/uni-quick-login/sms.png",
45
						"path": "/pages/ucenter/login-page/index/index?type=smsCode"
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
					},
					{
						"id": "weixin",
						"text": "微信登录",
						"logo": "/static/uni-quick-login/wechat.png",
					},
					{
						"id": "apple",
						"text": "苹果登录",
						"logo": "/static/uni-quick-login/apple.png",
					},
					{
						"id": "univerify",
						"text": "一键登录",
						"logo": "/static/uni-quick-login/univerify.png",
					},
					{
						"id": "qq",
						"text": "QQ登录", //暂未提供该登录方式的接口示例
						"logo": "/static/uni-quick-login/univerify.png",
					},
					{
						"id": "xiaomi",
						"text": "小米登录", //暂未提供该登录方式的接口示例
						"logo": "/static/uni-quick-login/univerify.png",
					},
					{
						"id": "sinaweibo",
						"text": "微博登录", //暂未提供该登录方式的接口示例
						"logo": "/static/uni-quick-login/univerify.png",
76
					}
DCloud_JSON's avatar
DCloud_JSON 已提交
77
				],
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
				oauthServices: [],
				config: {},
				univerifyStyle: { //一键登录弹出窗的样式配置参数
					"fullScreen": true, // 是否全屏显示,true表示全屏模式,false表示非全屏模式,默认值为false。
					"backgroundColor": "#ffffff", // 授权页面背景颜色,默认值:#ffffff
					"buttons": { // 自定义登陆按钮
						"iconWidth": "45px", // 图标宽度(高度等比例缩放) 默认值:45px
						"list": []
					},
					"privacyTerms": {
						"defaultCheckBoxState": false, // 条款勾选框初始状态 默认值: true   
						"textColor": "#BBBBBB", // 文字颜色 默认值:#BBBBBB  
						"termsColor": "#5496E3", //  协议文字颜色 默认值: #5496E3  
						"prefix": "我已阅读并同意", // 条款前的文案 默认值:“我已阅读并同意”  
						"suffix": "并使用本机号码登录", // 条款后的文案 默认值:“并使用本机号码登录”  
						"privacyItems": []
					}
95
				}
96
			}
97 98 99 100 101 102
		},
		watch: {
			agree(agree) {
				this.univerifyStyle.privacyTerms.defaultCheckBoxState = agree
			}
		},
103
		props: {
104 105 106
			agree: {
				type: Boolean,
				default () {
107 108
					return false
				}
109 110
			}
		},
111 112 113 114
		async created() {
			let servicesList = this.servicesList
			//去掉配置中不存在的
			servicesList = servicesList.filter(item => this.loginConfig.includes(item.id))
115
			//处理一键登录
116
			if (this.loginConfig.includes('univerify')) {
117 118
				this.univerifyStyle.privacyTerms.privacyItems = this.agreements
				//设置一键登录功能底下的快捷登陆按钮
119 120 121 122
				servicesList.forEach(({
					id,
					logo
				}) => {
123 124 125 126 127 128 129 130
					if (id != 'univerify') {
						this.univerifyStyle.buttons.list.push({
							"iconPath": logo,
							"provider": id
						})
					}
				})
			}
131 132
			//如果当前页面为默认登陆界面。当前第一优先级的“微信和苹果登陆”要隐藏,因为他已经被渲染在默认登陆界面顶部
			if (
133 134
				this.getRoute(1) == '/pages/ucenter/login-page/index/index' && ['weixin', 'apple'].includes(this
					.loginConfig[0])
135 136
			) {
				servicesList = servicesList.filter(item => item.id != this.loginConfig[0])
137
			}
138
			//去掉当前页面对应的登录选项
139
			this.servicesList = servicesList.filter(item => {
140
				let path = item.path ? item.path.split('?')[0] : '';
141
				return path != this.getRoute(1)
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
			})
			console.log('servicesList', servicesList, this.servicesList);
		},
		mounted() {
			// #ifdef APP-PLUS
			plus.oauth.getServices(oauthServices => {
				this.oauthServices = oauthServices
			}, err => {
				uni.showModal({
					title: '获取服务供应商失败:' + JSON.stringify(err),
					showCancel: false,
					confirmText: '知道了'
				});
				console.error('获取服务供应商失败:' + JSON.stringify(err));
			})
			// #endif
158 159 160 161 162 163 164
		},
		methods: {
			...mapMutations({
				setUserInfo: 'user/login'
			}),
			getRoute(n = 0) {
				let pages = getCurrentPages();
DCloud_JSON's avatar
DCloud_JSON 已提交
165
				// console.log('route-pages-length', pages.length);
166 167 168 169 170 171
				if (n > pages.length) {
					return ''
				}
				return '/' + pages[pages.length - n].route
			},
			to(path) {
172
				// console.log('比较', this.getRoute(2), path)
173 174 175 176
				if (this.getRoute(2) == path) { // 控制路由是重新打开还是返回,避免重复打开页面
					uni.navigateBack();
				} else {
					uni.navigateTo({
177 178
						url: path,
						animationType: 'slide-in-left'
179 180 181
					})
				}
			},
DCloud_JSON's avatar
DCloud_JSON 已提交
182
			login_before(type, navigateBack = true) {
183
				if (!this.agree && type != 'univerify') {
184 185 186 187 188
					return uni.showToast({
						title: '你未同意隐私政策协议',
						icon: 'none'
					});
				}
189 190 191
				uni.showLoading({
					mask: true
				})
192
				// console.log(arguments);
193
				let oauthService = this.oauthServices.find((service) => service.id == type)
194
				// console.log(type);
195 196

				// #ifdef APP-PLUS
DCloud_JSON's avatar
DCloud_JSON 已提交
197
				//请勿直接使用前端获取的unionid或openid直接用于登录,前端的数据都是不可靠的
198 199 200 201
				if (type == 'weixin') {
					return oauthService.authorize(({
							code
						}) => {
202
							// console.log(code);
203
							this.login({
204 205 206 207 208
								code
							}, type)
						},
						err => {
							uni.hideLoading()
209
							console.error(err);
210 211 212
							uni.showModal({
								content: JSON.stringify(err),
								showCancel: false
213
							});
214 215 216 217 218 219 220
						})
				}
				// #endif

				uni.login({
					"provider": type,
					"univerifyStyle": this.univerifyStyle,
DCloud_JSON's avatar
DCloud_JSON 已提交
221
					complete: (e) => {
222
						console.log(e);
DCloud_JSON's avatar
DCloud_JSON 已提交
223
					},
224 225 226 227 228
					success: async e => {
						console.log(e);
						if (type == 'apple') {
							let res = await this.getUserInfo({
								provider: "apple"
DCloud_JSON's avatar
DCloud_JSON 已提交
229
							})
230
							uni.hideLoading()
231 232
							Object.assign(e.authResult, res.userInfo)
						}
DCloud_JSON's avatar
DCloud_JSON 已提交
233
						// #ifdef MP-WEIXIN
DCloud_JSON's avatar
DCloud_JSON 已提交
234
						if (type == 'weixin') {
DCloud_JSON's avatar
DCloud_JSON 已提交
235 236 237 238 239
							return this.login({
								code: e.code
							}, type)
						}
						// #endif
240
						this.login(e.authResult, type)
241 242 243
					},
					fail: (err) => {
						uni.hideLoading()
DCloud_JSON's avatar
DCloud_JSON 已提交
244
						console.log(err);
245 246

						if (type == 'univerify') {
247
							if (err.metadata && err.metadata.error_data) {
248
								uni.showToast({
DCloud_JSON's avatar
DCloud_JSON 已提交
249
									title: "一键登录:" + err.metadata.error_data,
250 251 252
									icon: 'none'
								});
							}
253 254 255 256 257 258
							if (err.errMsg) {
								uni.showToast({
									title: "一键登录:" + err.errMsg,
									icon: 'none'
								});
							}
259 260
							switch (err.errCode) {
								case 30002:
DCloud_JSON's avatar
DCloud_JSON 已提交
261
									console.log('在一键登录界面,点击其他登录方式');
262 263
									break;
								case 30003:
DCloud_JSON's avatar
DCloud_JSON 已提交
264
									console.log('关闭了登录');
265 266 267 268
									if (navigateBack) {
										uni.navigateBack()
									}
									break;
269 270 271 272 273 274 275
								case 30006:
									uni.showModal({
										title: "登录服务初始化错误",
										content: err.metadata.error_data,
										showCancel: false,
										confirmText: '知道了',
									});
276
									break;
277 278 279 280 281
								case "30008":
									uni.showToast({
										title: '点击了第三方登陆',
										icon: 'none'
									});
282 283 284 285 286 287 288 289 290
									console.log('点击了第三方登陆,provider:', err.provider);
									let {
										path
									} = this.servicesList.find(item => item.id == err.provider) || {}
									console.log('path', path);
									if (path && path != this.getRoute(1)) { //存在路径,且并不是当前已经打开的路径
										this.to(path)
									} else {
										this.login_before(err.provider)
291 292 293
									}
									break;
								default:
DCloud_JSON's avatar
DCloud_JSON 已提交
294
									console.log(err);
295 296 297 298 299 300
									break;
							}
						}
					}
				})
			},
DCloud_JSON's avatar
DCloud_JSON 已提交
301
			login(params, type) { //联网验证登录
302 303 304 305
				console.log({
					params,
					type
				});
306
				let action = 'loginBy' + type.trim().toLowerCase().replace(type[0], type[0].toUpperCase())
307 308 309
				uniCloud.callFunction({
					name: 'uni-id-cf',
					data: {
310 311
						action,
						params
312
					},
313
					success: async ({
314 315
						result
					}) => {
316
						console.log("login-result", result);
317 318 319 320
						if (result.code === 0) {
							if (type == 'univerify') {
								uni.closeAuthView()
							}
321 322 323 324 325 326 327 328 329
							uni.hideLoading()
							delete result.userInfo.token
							
							// #ifdef MP-WEIXIN
							if (type == 'weixin' && !result.userInfo.nickname) {
								return this.$refs.userProfile.open(result.uid)
							}
							// #endif
							
330
							this.setUserInfo(result.userInfo)
331
							loginSuccess(result)
332 333 334 335 336
						} else {
							uni.showModal({
								content: result.msg,
								showCancel: false
							});
337 338 339 340 341
						}
					},
					complete: () => {
						uni.hideLoading()
					}
342
				})
343
			},
344 345 346
			doUserProfileNext(){
				loginSuccess()
			},
347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367
			async getUserInfo(e) {
				return new Promise((resolve, reject) => {
					uni.getUserInfo({
						...e,
						success: (res) => {
							resolve(res);
						},
						fail: (err) => {
							uni.showModal({
								content: JSON.stringify(err),
								showCancel: false
							});
							reject(err);
						}
					})
				})
			}
		}
	}
</script>

DCloud_JSON's avatar
DCloud_JSON 已提交
368
<style lang="scss" scoped>
369
	/* #ifndef APP-NVUE */
370 371 372 373 374 375 376
	view {
		display: flex;
		box-sizing: border-box;
		flex-direction: column;
	}

	/* #endif */
377 378 379
	.quick-login-box {
		flex-direction: row;
		width: 750rpx;
DCloud_JSON's avatar
DCloud_JSON 已提交
380 381 382
		justify-content: space-around;
		position: fixed;
		bottom: 10rpx;
DCloud_JSON's avatar
DCloud_JSON 已提交
383
		left: 0;
384 385 386 387 388 389 390 391 392 393 394 395 396 397
	}

	.item {
		flex-direction: column;
		justify-content: center;
		align-items: center;
		height: 200rpx;
	}

	.logo {
		width: 60rpx;
		height: 60rpx;
	}

DCloud_JSON's avatar
DCloud_JSON 已提交
398
	.login-title {
399 400 401
		margin-top: 4px;
		font-size: 26rpx;
	}
402
</style>