浏览代码

手机号登录

lilei 4 年之前
父节点
当前提交
4e3f7b37ca
共有 8 个文件被更改,包括 665 次插入3 次删除
  1. 133 0
      api/user.js
  2. 127 0
      components/uni-popup/image-txt-popup.vue
  3. 96 0
      components/uni-popup/popup-con.vue
  4. 5 0
      libs/validate.js
  5. 6 0
      pages.json
  6. 79 0
      pages/login/login.scss
  7. 4 3
      pages/login/login.vue
  8. 215 0
      pages/login/phoneLogin.vue

+ 133 - 0
api/user.js

@@ -0,0 +1,133 @@
+import axios from '@/libs/axios.js'
+
+//  axios.request()  第二个参数若为true则表示不传token
+
+// 登录
+export const login = (params) => {
+  return axios.request({
+    url: 'auth/login',
+    data: params,
+    method: 'post'
+  }, true)
+}
+//  校验手机号是否注册
+export const validateUser = params => {
+  return axios.request({
+    url: `org/apply/validateUser/${params.phone}`,
+    method: 'get'
+  }, true)
+}
+// 获取图片验证码
+export const getCaptcha = randomCode => {
+  return axios.request({
+    url: `org/apply/getCaptcha/${randomCode}`,
+    method: 'get',
+    responseType: 'blob',
+  }, true)
+}
+// 发送短信验证码
+export const sendVerifyCode = params => {
+  return axios.request({
+    url: 'org/apply/sendVerifyCode',
+    method: 'post',
+    data: params
+  }, true)
+}
+// 申请试用
+export const apply = params => {
+  return axios.request({
+    url: 'org/apply/apply',
+    method: 'post',
+    data: params
+  }, true)
+}
+// 获取门店名称
+export const getStore = (token) => {
+  return axios.request({
+    url: 'getStore',
+    method: 'get'
+  })
+}
+// 登出
+export const logout = () => {
+  return axios.request({
+    url: 'auth/logout',
+    method: 'get'
+  })
+}
+// 修改密码
+export const changePwd = params => {
+  return axios.request({
+    url: 'employee/changePWD',
+    method: 'post',
+    data: {
+      oldPassword: params.oldPassword,
+      password: params.password
+    }
+  }).then(res => res)
+} 
+//  忘记密码 校验手机号是否注册过
+export const memberGetByMobile = params => {
+  return axios.request({
+    url: 'member/getByMobile',
+    method: 'post',
+    data: params
+  }, true)
+}
+//  忘记密码 获取图片验证码
+export const memberCaptcha = randomCode => {
+  return axios.request({
+    url: `member/captcha/create/${randomCode}`,
+    method: 'get',
+    responseType: 'blob'
+  }, true)
+}
+//  忘记密码 发送短信验证码
+export const memberVerifyCode = params => {
+  return axios.request({
+    url: 'member/sendVerifyCode',
+    method: 'post',
+    data: params
+  }, true)
+}
+//  忘记密码 修改密码
+export const memberChangePwd = params => {
+  return axios.request({
+    url: 'member/changePwd',
+    method: 'post',
+    data: params
+  }, true)
+}
+//  忘记密码 校验短信验证码是否正确
+export const memberValidateVerifyCode = params => {
+  return axios.request({
+    url: 'member/validateVerifyCode',
+    method: 'post',
+    data: params
+  }, true)
+}
+// 获取通知消息未读数
+export const getUnreadCount = params => {
+  return axios.request({
+    url: 'noticeUser/queryNotReadCount',
+    method: 'post'
+  })
+}
+// 设置已读消息
+export const hasRead = params => {
+  return axios.request({
+    url: `noticeUser/setRead/${params.msg_id}`,
+    method: 'get'
+  })
+}
+// 查询所有消息
+export const getMessage = params => {
+  let url = `noticeUser/queryLike/${params.pageNo}/${params.pageSize}`
+  delete params.pageNo
+  delete params.pageSize
+  return axios.request({
+    url: url,
+    data: params,
+    method: 'post'
+  })
+}

+ 127 - 0
components/uni-popup/image-txt-popup.vue

@@ -0,0 +1,127 @@
+<template>
+	<view class="image-txt-wrap">
+		<image :src="captchaBase" class="image" @click="getCode"></image>
+		<text class="tip-txt">* 点击图片即可切换验证码</text>
+		<input v-model="captcha" @input="inpChange" class="item-inp" name="captcha" type="text" maxlength="4" placeholder="请输入上方的图形验证码" />
+		<button :type="btnType" size="mini" class="popup-button-yz" @click="verify">验证</button>
+	</view>
+</template>
+
+<script>
+	import { getCaptcha, memberCaptcha } from '@/api/user.js'
+	export default{
+		name: 'ImageTxtPopup',
+		props: {
+			changeImg: {
+				type: Boolean,
+				default: false
+			},
+			//  applyImageTxt申请试用   forgetImageTxt忘记密码
+			type: {
+				type: String,
+				default: ''
+			},
+		},
+		watch: {
+			changeImg(newV, oldV){
+				if(newV === true){
+					this.getCode()
+				}
+			}
+		},
+		data(){
+			return{
+				captchaBase: '',  //  图片验证码base64
+				captcha: '',  //  图文验证码
+				nowRandomCode: '',  // 当前随机码
+				btnType: 'default',  //  验证按钮type
+			}
+		},
+		created() {
+			this.getCode()
+		},
+		methods: {
+			//  获取验证码
+			getCode(){
+			  const _this = this
+			  //  6位随机数
+			  this.nowRandomCode = Math.random().toString().slice(-6)
+			  let portAddress = ''
+			  if(_this.type == 'applyImageTxt'){  //  申请试用  获取图片验证码
+				  portAddress = getCaptcha
+			  }else if(_this.type == 'forgetImageTxt'){  //  忘记密码  获取图片验证码
+				  portAddress = memberCaptcha
+			  }
+			  portAddress(this.nowRandomCode).then(res => {
+			    //  获取图片路径
+			    _this.captchaBase = 'data:image/png;base64,' + res.data
+			    // 显示图文验证码弹框
+			    _this.captcha = ''  //  清空图文输入内容
+			  })
+			},
+			//  验证码输入监听
+			inpChange(){
+				if(this.captcha.length == 4){
+					this.btnType = 'primary'
+				}else{
+					this.btnType = 'default'
+				}
+			},
+			//  验证
+			verify(){
+				if(!this.captcha){
+					uni.showToast({icon: 'none',title: '请输入上方的图形验证码'})
+					return
+				}else{
+					if(this.captcha.length != 4){
+						uni.showToast({icon: 'none',title: '请输入4位图形验证码'})
+						return
+					}
+					this.$emit('captchaImg', this.captcha, this.nowRandomCode)
+				}
+			},
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.image-txt-wrap{
+		line-height: 1.8;
+		.tip-txt{
+			display: block;
+			font-size: 24upx;
+			color: #999;
+			margin-bottom: 40upx;
+			text-align: center;
+		}
+		.item-inp{
+			background-color: #fff;
+			border: 2upx solid #dcdee2;
+			border-radius: 8upx;
+			color: #666;
+			display: inline-block;
+			font-size: 24upx;
+			height: 64upx;
+			line-height: 1.5;
+			padding: 8upx 14upx;
+			width: 100%;
+			box-sizing: border-box;
+		}
+		.image{
+			max-width: 100%;
+			width: 400upx;
+			height: 160upx;
+			margin: 30upx auto 20upx;
+			display: block;
+			img{
+				max-width: 100%;
+			}
+		}
+		.popup-button-yz{
+			display: block;
+			margin: 40upx auto 50upx;
+			width: 30%;
+			line-height: 2.8;
+		}
+	}
+</style>

+ 96 - 0
components/uni-popup/popup-con.vue

@@ -0,0 +1,96 @@
+<template>
+	<view class="popup-con">
+		<text class="popup-header">{{title}}</text>
+		<view class="popup-content">
+			<image-txt-popup :type="type" :changeImg="changeImg" @captchaImg="captchaImg"></image-txt-popup>
+		</view>
+		<view class="popup-footer">
+			<text class="popup-button" v-for="(item, index) in popBtn" :key="index" :style="{ color: item.color }">{{item.name}}</text>
+		</view>
+	</view>
+</template>
+
+<script>
+	import imageTxtPopup from '@/components/uni-popup/image-txt-popup.vue'
+	export default{
+		name: 'PopupCon',
+		props: {
+			//  applyImageTxt申请试用   forgetImageTxt忘记密码
+			type: {
+				type: String,
+				default: ''
+			},
+			title: {
+				type: String,
+				default: '标题'
+			},
+			//  操作按钮
+			popBtn: {
+				type: Array,
+				default: function (){
+				  return []
+				}
+			},
+			changeImg: {
+				type: Boolean,
+				default: false
+			}
+		},
+		components: {
+			imageTxtPopup
+		},
+		data(){
+			return{}
+		},
+		methods: {
+			captchaImg(captcha, nowRandomCode){
+				this.$emit('captchaImg', captcha, nowRandomCode)
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.popup-con{
+		box-sizing: border-box;
+		position: absolute;
+		top: 50%;
+		left: 50%;
+		transform: translate(-50%, -50%);
+		box-shadow: 0 8upx 24upx rgba(0,0,0,.15);
+		display: flex;
+		flex-direction: column;
+		padding: 30upx;
+		width: 600upx;
+		background-color: #fff;
+		border-radius: 20upx;
+		.popup-header{
+			margin-bottom: 20upx;
+			text-align: center;
+			font-weight: 700;
+			font-size: 32upx;
+			color: #333;
+			line-height: 1.8;
+		}
+		.popup-content{
+			font-size: 28upx;
+			color: #666;
+		}
+		.popup-footer{
+			display: flex;
+			flex-direction: row;
+			margin-top: 40upx;
+			.popup-button{
+				flex: 1;
+				text-align: center;
+				font-size: 28upx;
+				color: #3b4144;
+				line-height: 1.8;
+			}
+			.popup-confirm{
+				color: #57a3f3;
+			}
+		}
+	}
+	
+</style>

+ 5 - 0
libs/validate.js

@@ -0,0 +1,5 @@
+//  正则有效手机号码
+export const isvalidPhone = function (str) {
+  const reg = /^1[0-9]{10}$/
+  return reg.test(str)
+}

+ 6 - 0
pages.json

@@ -23,6 +23,12 @@
 				"navigationBarTitleText": "授权登录"
 			}
 		},
+		{
+			"path": "pages/login/phoneLogin",
+			"style": {
+				"navigationBarTitleText": "手机号登录"
+			}
+		},
 		{
 			"path": "pages/userCenter/index",
 			"style": {

+ 79 - 0
pages/login/login.scss

@@ -0,0 +1,79 @@
+.login-wrap, .forget-wrap, .apply-wrap{
+	background-color: #FFFFFF;
+	width: 100%;
+	height: 100vh;
+	box-sizing: border-box;
+	.logo{
+		display: flex;
+		justify-content: center;
+		padding: 100upx 0;
+	}
+	.login-form{
+		display: block;
+		width: 80%;
+		margin: 0 auto;
+		.form-item{
+			margin-bottom: 20upx;
+			position: relative;
+			display: flex;
+			align-items: center;
+			border: 1upx solid #dcdee2;
+			border-radius: 10upx;
+			.require-tip{
+				position: absolute;
+				left: 0;
+				top: 26upx;
+				color: red;
+			}
+			.item-inp{
+				flex-grow: 1;
+			}
+			.item-inp, .item-picker{
+				font-size: 30upx;
+				padding: 20upx 20upx;
+			}
+			.getcode-btn{
+				position: absolute;
+				right: 20upx;
+				top: 0;
+				font-size: 24upx;
+				margin-top: 14upx;
+			}
+		}
+		.flex-box{
+			display: flex;
+			justify-content: space-between;
+			font-size: 26upx;
+		}
+		.form-btn-con{
+			margin-top: 60upx;
+			.form-btn{
+				font-size: 32upx;
+				display: block;
+				line-height: 84upx;
+				margin: 0 auto;
+				background-color: #298bf2;
+				color: #fff;
+			}
+			uni-button.form-btn:after{
+				border: none;
+			}
+			.apply-btn{
+				display: block;
+				text-align: center;
+				margin-top: 50upx;
+			}
+		}
+	}
+	
+	.authUserYs{
+		text-align: center;
+		position: absolute;
+		bottom: 5%;
+		width: 100%;
+		font-size: 24upx;
+		text{
+			color: #ff0000;
+		}
+	}
+}

+ 4 - 3
pages/login/login.vue

@@ -8,7 +8,7 @@
 				<u-button shape="circle" class="login-btn" type="success" :hair-line="false" open-type="getPhoneNumber" @getphonenumber="getPhoneNumber">
 					微信登陆
 				</u-button>
-				<u-button shape="circle" class="login-btn" type="primary">
+				<u-button shape="circle" class="login-btn" @click="phoneLogin" type="primary">
 					手机号码登录
 				</u-button>
 			</view>
@@ -105,9 +105,10 @@
 					}
 				})
 			},
-			gotoHome () {
+			// 手机号登录
+			phoneLogin () {
 			  wx.reLaunch({
-			    url: '/pages/index/index'
+			    url: '/pages/login/phoneLogin'
 			  })
 			}
 		}

+ 215 - 0
pages/login/phoneLogin.vue

@@ -0,0 +1,215 @@
+<template>
+	<view class="forget-wrap">
+		<view class="logo">
+			<u-image src="/static/logo.png" width="120" height="120" ></u-image>
+		</view>
+		<form class="login-form" @submit="formSubmit">
+			<view class="form-item">
+				<input v-model="form.phone" class="item-inp" name="phone" type="number" maxlength="11" placeholder="请输入登录手机号" />
+			</view>
+			<view class="form-item">
+				<input v-model="form.verifyCode" class="item-inp" name="verifyCode" type="number" maxlength="6" placeholder="请输入短信验证码" />
+				<button class="getcode-btn" :disabled="isDisable" @click="getCodeValidate">{{nowVal}}</button>
+			</view>
+			<view class="form-btn-con">
+				<button class="form-btn" @click="goStep">登录</button>
+			</view>
+		</form>
+		<!-- 图文验证码 -->
+		<uni-popup ref="imageTxtPopup" type="center">
+			<popup-con type="forgetImageTxt" title="图文验证码" :popBtn="popBtn" :changeImg="changeImg" @captchaImg="captchaImg"></popup-con>
+		</uni-popup>
+	</view>
+</template>
+
+<script>
+	import { isvalidPhone } from '@/libs/validate.js'
+	import uniPopup from '@/components/uni-popup/uni-popup.vue'
+	import popupCon from '@/components/uni-popup/popup-con.vue'
+	import { memberVerifyCode, memberChangePwd, memberValidateVerifyCode, memberGetByMobile } from '@/api/user.js'
+	export default{
+		components: {
+			uniPopup,
+			popupCon
+		},
+		data(){
+			return{
+				state: 0,  //  忘记密码当前状态
+				form: {
+					phone: '',
+					verifyCode: '',
+					password: '',
+					passwords: ''
+				},
+				nowVal: '获取验证码',  //  按钮显示内容
+				count: '',  //  当前秒数
+				timer: null,  //  倒计时
+				isDisable: false,  //  是否禁止获取验证码
+				popBtn: [],  //  name为操作按钮名称,color为操作按钮颜色值
+				changeImg: false,  //  是否重新更换图形验证码
+				randomCode: '',  //  图片验证码随机码
+			}
+		},
+		onLoad(opts) {
+			if(opts.username){
+				this.form.phone = opts.username
+			}
+		},
+		methods: {
+			//  下一步
+			goStep(){
+				const _this = this
+				//  表单校验
+				if(this.form.phone == ''){
+					uni.showToast({icon: 'none',title: '请输入登录手机号'})
+					return
+				}
+				if(!isvalidPhone(this.form.phone)){
+				  uni.showToast({icon: 'none',title: '请输入正确的手机号码'})
+				  return
+				}
+				if(this.form.verifyCode == ''){
+					uni.showToast({icon: 'none',title: '请输入验证码'})
+					return
+				}
+				//  校验短信验证码是否正确
+				const obj = {}
+				obj.phone = _this.form.phone,
+				obj.random = _this.randomCode,  // 当前随机码
+				obj.verifyCode = _this.form.verifyCode
+				memberValidateVerifyCode(obj).then(res => {
+				  if(res.status == 200){
+				    _this.state = 1
+				  }else{
+					  uni.showToast({icon: 'none',title: res.message})
+				  }
+				})
+			},
+			//  表单提交
+			formSubmit(){
+				const _this = this
+				if(this.form.password == ''){
+					uni.showToast({icon: 'none',title: '请输入新密码'})
+					return
+				}
+				if(this.form.password.length < 6 || this.form.password.length > 12){
+					uni.showToast({icon: 'none',title: '请输入6-12位新密码'})
+					return
+				}
+				if(this.form.passwords == ''){
+					uni.showToast({icon: 'none',title: '请再次输入新密码'})
+					return
+				}
+				if(this.form.password != this.form.passwords){
+					uni.showToast({icon: 'none',title: '两次密码输入不一致'})
+					return
+				}
+				const obj = {}
+				obj.phone = _this.form.phone,
+				obj.random = _this.randomCode,  // 当前随机码
+				obj.verifyCode = _this.form.verifyCode,
+				obj.password = _this.form.password
+				memberChangePwd(obj).then(res => {
+					if(res.status == 200){
+						//  将修改后的账号密码  重新存储
+						_this.$u.vuex('vuex_user.account', _this.form.phone)
+						_this.$u.vuex('vuex_user.password', '')
+						clzConfirm({
+						    title: '提示',
+						    content: '修改成功',
+							confirmText: '去登录',
+							showCancel: false,
+							success: function (ret) {
+						        if (ret.confirm||ret.index==0) {
+									uni.reLaunch({
+										url: '/pages/login/login'
+									})
+						        }
+						    }
+						})
+					}
+				})
+			},
+			//  获取验证码
+			getCodeValidate(){
+				if(this.form.phone){
+					if(!isvalidPhone(this.form.phone)){
+						uni.showToast({icon: 'none',title: '请输入正确的手机号码'})
+						return
+					}else{
+						//  校验手机号是否注册过
+						memberGetByMobile({phone: this.form.phone}).then(res => {
+							if(res.status == 200){
+								//  图文验证码
+								this.$refs.imageTxtPopup.open()
+							}else{
+								uni.showToast({icon: 'none',title: res.message})
+							}
+						})
+					}
+				}else{
+					uni.showToast({icon: 'none',title: '请先输入手机号'})
+				}
+			},
+			//  开始倒计时
+			getCodeFun(){
+				const TIME_COUNT = 60
+				if (!this.timer) {
+				  this.count = TIME_COUNT
+				  this.timer = setInterval(() => {
+				    if (this.count > 0 && this.count <= TIME_COUNT) {
+				      this.count--
+				      this.nowVal = this.count + 's后重发'
+				      this.isDisable = true
+				    } else {
+				      this.nowVal = '重新获取验证码'
+				      clearInterval(this.timer)
+				      this.timer = null
+				      this.isDisable = false
+				    }
+				  }, 1000)
+				}
+			},
+			//  图文验证码
+			captchaImg(code, nowRandomCode){
+				this.captchaVerify(code, nowRandomCode)
+			},
+			//  验证图片验证码
+			captchaVerify(code, nowRandomCode){
+				const _this = this
+				let obj = {}
+				obj.phone = this.form.phone
+				obj.random = nowRandomCode
+				obj.captcha = code
+				//  短信验证码
+				memberVerifyCode(obj).then(res => {
+					console.log(JSON.stringify(res))
+					if(res.status == 200){  //  验证码输入正确
+						_this.randomCode = nowRandomCode  //  图片验证码随机码
+						//  关闭   图形验证码 弹框
+						_this.$refs.imageTxtPopup.close()
+						//  开启倒计时
+						this.getCodeFun()
+						uni.showToast({icon: 'none',title: '验证码发送成功'})
+					}else {  //  验证码输入错误
+						_this.randomCode = ''
+						//  切换验证码重新校验
+						_this.changeImg = false
+						_this.$nextTick(function(){
+							_this.changeImg = true
+						})
+						uni.showToast({icon: 'none',title: res.message})
+					}
+				})
+			},
+		}
+	}
+</script>
+<style scoped lang="scss">
+	@import './login.scss';
+	.getcode-btn {
+		background-color: #298bf2 !important;
+		color: #fff !important;
+		border: none !important;
+	}
+</style>