Files
crmeb-mp/pages/users/login/index.vue

901 lines
21 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="wrapper" :style="colorStyle">
<view class="bag">
<img :src="imgHost+'/statics/images/users/login-bg.jpg'" alt="" srcset="">
</view>
<!-- #ifdef MP -->
<view class="title-bar" style="height: 43px;">
<view class="icon" @click="back" v-if="!isHome">
<image src="../static/left.png"></image>
</view>
<view class="icon" @click="home" v-else>
<image src="../static/home.png"></image>
</view>
{{pageTitle}}
</view>
<!-- #endif -->
<view class="page-msg">
<view class="title">
{{current ? '快速登录' :'账号登录'}}
</view>
<view class="tip">
首次登录会自动注册
</view>
</view>
<view class="page-form">
<view class="item">
<input type='number' placeholder='请输入手机号码' placeholder-class='placeholder' v-model="account"
:maxlength="11" :adjust-position="false"></input>
</view>
<view class="item acea-row row-between-wrapper" v-if="!current">
<input type='password' placeholder='请输入密码' placeholder-class='placeholder'
class="codeIput" v-model="password" :adjust-position="false"></input>
<view class="line"></view>
<navigator class="code font-num" hover-class="none" url="/pages/users/retrievePassword/index">
忘记密码
</navigator>
</view>
<view class="item acea-row row-between-wrapper" v-else>
<input type='number' placeholder='请输入验证码' placeholder-class='placeholder' :maxlength="6"
class="codeIput" v-model="captcha"></input>
<view class="line">
</view>
<button class="code font-num" :class="disabled === true ? 'on' : ''" :disabled='disabled' @click="code">
{{ text }}
</button>
</view>
<view class="btn" @click="submitData">
立即登录
</view>
<view class="text-center fs-32 text--w111-999 mt-32" @click="current = !current">{{current ? '账号登录' :'手机号登录'}}</view>
<!-- #ifdef APP-PLUS -->
<view class="appLogin" v-if="!appLoginStatus && !appleLoginStatus">
<view class="hds">
<span class="line"></span>
<p>其他方式登录</p>
<span class="line"></span>
</view>
<view class="btn-wrapper">
<view class="btn wx" @click="wxLogin">
<span class="iconfont icon-ic_wechat"></span>
</view>
<view class="btn pingguo" @click="appleLogin" v-if="appleShow">
<view class="iconfont icon-ic_apple"></view>
</view>
</view>
</view>
<!-- #endif -->
</view>
<view class="protocol">
<checkbox-group @click.stop='ChangeIsDefault'>
<checkbox :class="inAnimation?'trembling':''"
@animationend='inAnimation=false'
:checked="protocol ? true : false"
color="#ffffff" backgroundColor="#ffffff"
activeBackgroundColor="var(--view-theme)"
activeBorderColor="var(--view-theme)"/> <text @click.stop='ChangeIsDefault'>已阅读并同意</text>
<text class="main-color" @click.stop="privacy('user')">《用户协议》</text>
与<text class="main-color" @click.stop="privacy('privacy')">《隐私协议》</text>
</checkbox-group>
<!-- #ifdef APP-PLUS -->
<!-- 备案号:商店审核要求应用内可见(未登录也能看到);号未下发时该行不渲染,取值见 config/legal.js -->
<view class="beian" v-if="beianNo">APP 备案号:{{ beianNo }}</view>
<!-- #endif -->
</view>
<Verify v-if="!disabled" @success="success" :captchaType="captchaType" :imgSize="{ width: '330px', height: '155px' }"
ref="verify"></Verify>
</view>
</template>
<script>
import sendVerifyCode from "@/mixins/SendVerifyCode";
import {
loginH5,
loginMobile,
registerVerify,
register,
getCodeApi,
getUserInfo,
appleLogin
} from "@/api/user";
import attrs, {
required,
alpha_num,
chs_phone
} from "@/utils/validate";
import {
getLogo
} from "@/api/public";
// import cookie from "@/utils/store/cookie";
import {
VUE_APP_API_URL
} from "@/utils";
// #ifdef APP-PLUS
import {
wechatAppAuth
} from '@/api/api.js'
// #endif
const BACK_URL = "login_back_url";
import colors from '@/mixins/color.js';
import Verify from '../components/verify/verify.vue';
import { HTTP_REQUEST_URL, CAPTCHA_TYPE } from '@/config/app';
import legal from '@/config/legal.js';
export default {
name: "Login",
components: {
Verify
},
mixins: [sendVerifyCode, colors],
data: function() {
return {
captchaType: CAPTCHA_TYPE,
inAnimation: false,
protocol: false,
imgHost: HTTP_REQUEST_URL,
navList: ["快速登录", "账号登录"],
current: true,
account: "",
password: "",
captcha: "",
formItem: 1,
type: "login",
logoUrl: "",
keyCode: "",
codeUrl: "",
codeVal: "",
isShowCode: false,
appLoginStatus: false, // 微信登录强制绑定手机号码状态
appUserInfo: null, // 微信登录保存的用户信息
appleLoginStatus: false, // 苹果登录强制绑定手机号码状态
appleUserInfo: null,
appleShow: false, // 苹果登录版本必须要求ios13以上的
keyLock: true,
copyrightContext:'',
// App 备案号(商店要求应用内可见):号未下发时为空 → 该行不渲染
beianNo: legal.APP_BEIAN_NO,
};
},
watch: {
formItem: function(nval, oVal) {
if (nval == 1) {
this.type = 'login'
} else {
this.type = 'register'
}
}
},
onLoad() {
let self = this
uni.getSystemInfo({
success: (res) => {
if (res.platform.toLowerCase() == 'ios' && this.getSystem(res.system)) {
self.appleShow = true
}
}
});
},
mounted() {
// this.getCode();
this.getLogoImage();
},
methods: {
domainTap(url){
// #ifdef H5
location.href = url
// #endif
// #ifdef MP || APP-PLUS
uni.navigateTo({
url: `/pages/annex/web_view/index?url=${url}`
});
// #endif
},
changeMsg() {
this.inAnimation = true;
},
ChangeIsDefault(e) {
this.$set(this, 'protocol', !this.protocol);
},
// IOS 版本号判断
getSystem(system) {
let str
system.toLowerCase().indexOf('ios') === -1 ? str = system : str = system.split(' ')[1]
if (str.indexOf('.'))
return str.split('.')[0] >= 13
return str >= 13
},
// 苹果登录
appleLogin() {
let self = this
this.account = ''
this.captcha = ''
if (!self.protocol) {
this.inAnimation = true
return self.$util.Tips({
title: '请先阅读并同意协议'
});
}
uni.showLoading({
title: '登录中'
})
uni.login({
provider: 'apple',
timeout: 10000,
success(loginRes) {
uni.getUserInfo({
provider: 'apple',
success: function(infoRes) {
self.appleUserInfo = infoRes.userInfo
self.appleLoginApi()
},
fail() {
uni.showToast({
title: '获取用户信息失败',
icon: 'none',
duration: 2000
})
},
complete() {
uni.hideLoading()
}
});
},
fail(error) {
console.log(error)
}
})
},
// 苹果登录Api
appleLoginApi() {
let self = this
appleLogin({
openId: self.appleUserInfo.openId,
email: self.appleUserInfo.email || '',
phone: this.account,
captcha: this.captcha
}).then(({
data
}) => {
if (data.isbind) {
uni.showModal({
title: '提示',
content: '请绑定手机号后,继续操作',
showCancel: false,
success: function(res) {
if (res.confirm) {
self.current = true
self.appleLoginStatus = true
}
}
});
} else {
self.$store.commit("LOGIN", {
'token': data.token,
'time': data.expires_time - self.$Cache.time()
});
let backUrl = self.$Cache.get(BACK_URL) || "/pages/index/index";
self.$Cache.clear(BACK_URL);
self.$store.commit("SETUID", data.userInfo.uid);
self.$store.commit("UPDATE_USERINFO", data.userInfo);
uni.reLaunch({
url: backUrl
});
}
}).catch(error => {
uni.showModal({
title: '提示',
content: `错误信息${error}`,
success: function(res) {
if (res.confirm) {
console.log('用户点击确定');
} else if (res.cancel) {
console.log('用户点击取消');
}
}
});
})
},
// App微信登录
wxLogin() {
if (!this.protocol) {
this.inAnimation = true
return this.$util.Tips({
title: '请先阅读并同意协议'
});
}
let self = this
this.account = ''
this.captcha = ''
uni.showLoading({
title: '登录中'
})
uni.login({
provider: 'weixin',
success: function(loginRes) {
// 获取用户信息
uni.getUserInfo({
provider: 'weixin',
success: function(infoRes) {
self.appUserInfo = infoRes.userInfo
self.wxLoginApi()
},
fail() {
uni.showToast({
title: '获取用户信息失败',
icon: 'none',
duration: 2000
})
},
complete() {
uni.hideLoading()
}
});
},
fail() {
uni.showToast({
title: '登录失败',
icon: 'none',
duration: 2000
})
}
});
},
submitData(){
if(this.current){
this.loginMobile()
}else{
this.submit()
}
},
wxLoginApi() {
let self = this
wechatAppAuth({
userInfo: self.appUserInfo,
phone: this.account,
code: this.captcha
}).then(({
data
}) => {
if (data.isbind) {
uni.showModal({
title: '提示',
content: '请绑定手机号后,继续操作',
showCancel: false,
success: function(res) {
if (res.confirm) {
self.current = true
self.appLoginStatus = true
}
}
});
} else {
self.$store.commit("LOGIN", {
'token': data.token,
'time': data.expires_time - self.$Cache.time()
});
let backUrl = self.$Cache.get(BACK_URL) || "/pages/index/index";
self.$Cache.clear(BACK_URL);
self.$store.commit("SETUID", data.userInfo.uid);
self.$store.commit("UPDATE_USERINFO", data.userInfo);
uni.reLaunch({
url: backUrl
});
}
}).catch(error => {
uni.showModal({
title: '提示',
content: `错误信息${error}`,
success: function(res) {
if (res.confirm) {
console.log('用户点击确定');
} else if (res.cancel) {
console.log('用户点击取消');
}
}
});
})
},
again() {
this.codeUrl =
VUE_APP_API_URL +
"/sms_captcha?" +
"key=" +
this.keyCode +
Date.parse(new Date());
},
success(data) {
this.$refs.verify.hide()
getCodeApi()
.then(res => {
this.keyCode = res.data.key;
this.getCode(data);
})
.catch(res => {
this.$util.Tips({
title: res
});
});
},
code() {
let that = this
if (!that.protocol) {
this.inAnimation = true
return that.$util.Tips({
title: '请先阅读并同意协议'
});
}
if (!that.account) return that.$util.Tips({
title: '请填写手机号码'
});
if (!/^1(3|4|5|7|8|9|6)\d{9}$/i.test(that.account)) return that.$util.Tips({
title: '请输入正确的手机号码'
});
// getCodeApi()
// .then(res => {
// that.keyCode = res.data.key;
// that.getCode();
// })
// .catch(res => {
// that.$util.Tips({
// title: res
// });
// });
this.$refs.verify.show()
},
async getLogoImage() {
let that = this;
getLogo(2).then(res => {
that.logoUrl = res.data.logo_url;
that.copyrightContext = res.data.copyrightContext;
});
},
async loginMobile() {
let that = this;
if (!that.protocol) {
this.inAnimation = true
return that.$util.Tips({
title: '请先阅读并同意协议'
});
}
if (!that.account) return that.$util.Tips({
title: '请填写手机号码'
});
if (!/^1(3|4|5|7|8|9|6)\d{9}$/i.test(that.account)) return that.$util.Tips({
title: '请输入正确的手机号码'
});
if (!that.captcha) return that.$util.Tips({
title: '请填写验证码'
});
if (!/^[\w\d]+$/i.test(that.captcha)) return that.$util.Tips({
title: '请输入正确的验证码'
});
if (that.appLoginStatus) {
that.wxLoginApi()
} else if (that.appleLoginStatus) {
that.appleLoginApi()
} else {
if (this.keyLock) {
this.keyLock = !this.keyLock
} else {
return that.$util.Tips({
title: '请勿重复点击'
});
}
loginMobile({
phone: that.account,
captcha: that.captcha,
spread_spid: that.$Cache.get("spread")
})
.then(res => {
let data = res.data;
that.$store.commit("LOGIN", {
'token': data.token,
'time': data.expires_time - this.$Cache.time()
});
let backUrl = that.$Cache.get(BACK_URL) || "/pages/index/index";
that.$Cache.clear(BACK_URL);
getUserInfo().then(res => {
this.keyLock = true
that.$store.commit("SETUID", res.data.uid);
that.$store.commit("UPDATE_USERINFO", res.data);
if (backUrl.indexOf('/pages/users/login/index') !== -1) {
backUrl = '/pages/index/index';
}
uni.reLaunch({
url: backUrl
});
})
})
.catch(res => {
this.keyLock = true
that.$util.Tips({
title: res
});
});
}
},
async register() {
let that = this;
if (!that.account) return that.$util.Tips({
title: '请填写手机号码'
});
if (!/^1(3|4|5|7|8|9|6)\d{9}$/i.test(that.account)) return that.$util.Tips({
title: '请输入正确的手机号码'
});
if (!that.captcha) return that.$util.Tips({
title: '请填写验证码'
});
if (!/^[\w\d]+$/i.test(that.captcha)) return that.$util.Tips({
title: '请输入正确的验证码'
});
if (!that.password) return that.$util.Tips({
title: '请填写密码'
});
if (/^([0-9]|[a-z]|[A-Z]){0,6}$/i.test(that.password)) return that.$util.Tips({
title: '您输入的密码过于简单'
});
register({
account: that.account,
captcha: that.captcha,
password: that.password,
spread_spid: that.$Cache.get("spread")
})
.then(res => {
that.$util.Tips({
title: res
});
that.formItem = 1;
})
.catch(res => {
that.$util.Tips({
title: res
});
});
},
async getCode(data){
let that = this;
if (!that.account) return that.$util.Tips({
title: '请填写手机号码'
});
if (!/^1(3|4|5|7|8|9|6)\d{9}$/i.test(that.account)) return that.$util.Tips({
title: '请输入正确的手机号码'
});
if (that.formItem == 2) that.type = "register";
await registerVerify({
phone: that.account,
type: that.type,
key: that.keyCode,
captchaType: CAPTCHA_TYPE,
captchaVerification: data.captchaVerification
})
.then(res => {
that.$util.Tips({
title: res.msg
});
that.sendCode();
})
.catch(res => {
this.$refs.verify.refresh()
that.$util.Tips({
title: res
});
});
},
async submit() {
let that = this;
if (!that.protocol) {
this.inAnimation = true
return that.$util.Tips({
title: '请先阅读并同意协议'
});
}
if (!that.account) return that.$util.Tips({
title: '请填写账号'
});
if (!/^[\w\d]{5,16}$/i.test(that.account)) return that.$util.Tips({
title: '请输入正确的账号'
});
if (!that.password) return that.$util.Tips({
title: '请填写密码'
});
if (this.keyLock) {
this.keyLock = !this.keyLock
} else {
return that.$util.Tips({
title: '请勿重复点击'
});
}
loginH5({
account: that.account,
password: that.password,
spread_spid: that.$Cache.get("spread")
})
.then(({
data
}) => {
that.$store.commit("LOGIN", {
'token': data.token,
'time': data.expires_time - this.$Cache.time()
});
let backUrl = that.$Cache.get(BACK_URL) || "/pages/index/index";
that.$Cache.clear(BACK_URL);
getUserInfo().then(res => {
this.keyLock = true
that.$store.commit("SETUID", res.data.uid);
that.$store.commit("UPDATE_USERINFO", res.data);
uni.reLaunch({
url: backUrl
});
}).catch(error => {
this.keyLock = true
})
})
.catch(e => {
this.keyLock = true
that.$util.Tips({
title: e
});
});
},
privacy(type) {
uni.navigateTo({
url: "/pages/users/privacy/index?type=" + type
})
}
}
};
</script>
<style lang="scss" scoped>
/deep/ checkbox .wx-checkbox-input.wx-checkbox-input-checked {
border: 1px solid var(--view-theme) !important;
background-color: var(--view-theme) !important;
width: 28rpx;
height: 28rpx;
font-size: 24rpx;
color: #fff !important;
}
.wrapper {
background-color: #fff;
min-height: 100vh;
position: relative;
.bag {
position: absolute;
top: 0;
left: 0;
width: 100%;
z-index: 0;
/* #ifdef H5 */
z-index: 0;
/* #endif */
img {
width: 100%;
height: 544rpx;
}
}
.page-msg {
padding-top: 160rpx;
margin-left: 72rpx;
z-index: 2;
position: relative;
.title {
font-size: 48rpx;
font-weight: 500;
color: #333333;
line-height: 68rpx;
}
.tip {
font-size: 28rpx;
font-weight: 400;
color: #333333;
line-height: 40rpx;
}
}
.page-form {
width: 606rpx;
margin: 100rpx auto 0 auto;
z-index: 2;
position: relative;
.item {
width: 100%;
height: 88rpx;
background: #F5F5F5;
border-radius: 45rpx;
padding: 24rpx 48rpx;
margin-bottom: 32rpx;
input {
width: 100%;
height: 100%;
font-size: 32rpx;
}
.placeholder {
color: #BBBBBB;
font-size: 28rpx;
}
input.codeIput {
width: 300rpx;
}
.line {
width: 2rpx;
height: 28rpx;
background: #CCCCCC;
}
.code {
font-size: 28rpx;
color: var(--view-theme);
background-color: rgba(255, 255, 255, 0);
}
.code.on {
color: #BBBBBB !important;
}
}
.btn {
width: 606rpx;
height: 88rpx;
background: var(--view-theme);
border-radius: 200rpx 200rpx 200rpx 200rpx;
display: flex;
justify-content: center;
align-items: center;
font-size: 32rpx;
font-family: PingFang SC-Regular, PingFang SC;
font-weight: 400;
color: #FFFFFF;
line-height: 44rpx;
margin-top: 48rpx;
letter-spacing: 1px;
}
}
}
.title-bar {
position: relative;
display: flex;
align-items: center;
justify-content: center;
font-size: 34rpx;
font-weight: 500;
color: #333333;
line-height: 48rpx;
}
.icon {
position: absolute;
left: 30rpx;
top: 0;
display: flex;
align-items: center;
justify-content: center;
width: 80rpx;
height: 80rpx;
image {
width: 35rpx;
height: 35rpx;
}
}
.protocol {
position: fixed;
bottom: 52rpx;
left: 0;
width: 100%;
margin: 0 auto;
color: #999999;
font-size: 24rpx;
line-height: 22rpx;
text-align: center;
bottom: calc(52rpx + constant(safe-area-inset-bottom)); ///兼容 IOS<11.2/
bottom: calc(52rpx + env(safe-area-inset-bottom)); ///兼容 IOS>11.2/
.main-color {
color: var(--view-theme);
}
/* App 备案号:字号比协议再小一档,避免抢协议勾选的视觉重心 */
.beian {
margin-top: 14rpx;
font-size: 20rpx;
line-height: 28rpx;
color: #b5b5b5;
}
.trembling {
animation: shake 0.6s;
}
}
.appLogin {
margin-top: 60rpx;
.hds {
display: flex;
justify-content: center;
align-items: center;
font-size: 24rpx;
color: #B4B4B4;
.line {
width: 68rpx;
height: 1rpx;
background: #CCCCCC;
}
p {
margin: 0 20rpx;
}
}
.btn-wrapper {
display: flex;
align-items: center;
justify-content: center;
margin-top: 30rpx;
.btn {
display: flex;
align-items: center;
justify-content: center;
width: 68rpx;
height: 68rpx;
border-radius: 50%;
}
.apple-btn {
display: flex;
align-items: center;
justify-content: center;
width: 246rpx;
height: 66rpx;
margin-left: 30rpx;
background: #EAEAEA;
border-radius: 34rpx;
font-size: 24rpx;
.icon-s-pingguo {
color: #333;
margin-right: 10rpx;
font-size: 34rpx;
}
}
.iconfont {
font-size: 40rpx;
color: #fff;
}
.wx {
background-color: #61C64F;
}
.mima {
background-color: #28B3E9;
}
.yanzheng {
background-color: #F89C23;
}
.pingguo {
margin-left: 60rpx;
background-color: #000;
}
}
}
</style>