Files
hhrs/pages/index/login.vue
T

306 lines
6.8 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="page">
<!-- xuchao: 顶部导航(返回+页面名称) -->
<view class="nav-bar">
<view class="nav-back" @click="goBack">
<u-icon name="arrow-left" color="#1a1818" size="40"></u-icon>
</view>
<text class="nav-title">手机号登录</text>
</view>
<!-- 标题区 -->
<view class="title-area">
<text class="title">手机号登录</text>
<text class="subtitle">请使用真实手机号登录</text>
</view>
<!-- 表单区 -->
<view class="form-area">
<view class="input-item">
<input class="input-field" type="number" maxlength="11" v-model="phone" placeholder="请输入手机号码" />
</view>
<view class="input-item code-row">
<input class="input-field" type="number" maxlength="4" v-model="code" placeholder="请输入验证码" />
<text class="code-btn" :class="{ disabled: countdown > 0 }" @click="sendCode">
{{ countdown > 0 ? countdown + '秒后重新获取' : '获取验证码' }}
</text>
</view>
</view>
<!-- 登录按钮 -->
<view class="login-btn" @click="onLogin">立即登录</view>
<!-- 协议区 -->
<view class="agreement-area">
<view class="checkbox" :class="{ checked: agreed }" @click="agreed = !agreed">
<text class="check-icon" v-if="agreed">✓</text>
</view>
<text class="agreement-text" @click="agreed = !agreed">我已阅读并同意</text>
<text class="agreement-link" @click.stop="goAgreement('user')">《用户协议》</text>
<text class="agreement-text" @click="agreed = !agreed">和</text>
<text class="agreement-link" @click.stop="goAgreement('privacy')">《隐私协议》</text>
</view>
</view>
</template>
<script>
export default {
data() {
return {
phone: '',
code: '',
countdown: 0,
timer: null,
agreed: true,
redirect: ''
}
},
onLoad(options) {
this.redirect = options.redirect || ''
},
onUnload() {
if (this.timer) {
clearInterval(this.timer)
}
},
methods: {
sendCode() {
if (this.countdown > 0) return
if (!this.phone || !/^1\d{10}$/.test(this.phone)) {
uni.showToast({ title: '请输入正确的手机号', icon: 'none' })
return
}
this.$u.api.sendLoginVerifyCode({ smsType: 'CIB_LOGIN', mobile: this.phone }).then(res => {
if (res.errcode === 0) {
uni.showToast({ title: '验证码已发送', icon: 'success' })
} else {
uni.showToast({ title: res.errmsg || '发送失败', icon: 'none' })
}
}).catch(() => {
uni.showToast({ title: '发送失败', icon: 'none' })
})
this.countdown = 60
this.timer = setInterval(() => {
this.countdown--
if (this.countdown <= 0) {
clearInterval(this.timer)
this.timer = null
}
}, 1000)
},
onLogin() {
if (!this.phone || !/^1\d{10}$/.test(this.phone)) {
uni.showToast({ title: '请输入正确的手机号', icon: 'none' })
return
}
if (!this.code || this.code.length < 4) {
uni.showToast({ title: '请输入4位验证码', icon: 'none' })
return
}
if (!this.agreed) {
uni.showToast({ title: '请同意用户协议和隐私协议', icon: 'none' })
return
}
this.$u.api.checkerLogin({ password: '1232321', mobile: this.phone, verifyCode: this.code }).then(res => {
if (res.errcode === 0) {
uni.setStorageSync('token', res.data.token)
uni.setStorageSync('phone', this.phone)
this.$u.api.getEligibility({ phone: this.phone, identityNo: '', name: '' }).then(eRes => {
if (eRes.errcode === 0) {
uni.setStorageSync('isAuth', eRes.data.isAuth)
uni.setStorageSync('hasWin', eRes.data.hasWin)
uni.setStorageSync('cardNumber', eRes.data.cardNumber)
uni.setStorageSync('expiresTime', eRes.data.expiresTime)
}
}).finally(() => {
if (this.redirect === 'rights') {
const isAuth = uni.getStorageSync('isAuth')
const hasWin = uni.getStorageSync('hasWin')
let status = 'auth'
if (isAuth) {
status = hasWin ? 'info' : 'noWin'
}
uni.redirectTo({ url: `/pages/rights/rights?status=${status}` })
} else {
uni.navigateBack()
}
})
} else {
uni.showToast({ title: res.errmsg || '登录失败', icon: 'none' })
}
}).catch(() => {
uni.showToast({ title: '登录失败', icon: 'none' })
})
},
goAgreement(type) {
const url = type === 'user' ? '/pages/agreement/user' : '/pages/agreement/privacy'
uni.navigateTo({ url })
},
goBack() {
// xuchao: 直接通过链接进入(无历史栈)时回到首页,避免返回无响应
const pages = getCurrentPages()
if (pages.length > 1) {
uni.navigateBack()
} else {
uni.reLaunch({ url: '/pages/index/index' })
}
}
}
}
</script>
<style>
.page {
height: 100vh;
background-color: #ffffff;
padding: 0 40rpx;
display: flex;
flex-direction: column;
overflow: hidden;
}
/* 标题区 */
.title-area {
margin-top: 160rpx;
margin-bottom: 80rpx;
}
.title {
font-size: 44rpx;
font-weight: bold;
color: #1a1a1a;
display: block;
text-align: center;
margin-bottom: 16rpx;
}
.subtitle {
font-size: 26rpx;
color: #999999;
display: block;
text-align: center;
}
/* 表单区 */
.form-area {
margin-bottom: 40rpx;
}
.input-item {
border: 1px solid #e5e5e5;
border-radius: 12rpx;
margin-bottom: 24rpx;
overflow: hidden;
}
.input-field {
height: 96rpx;
padding: 0 24rpx;
font-size: 28rpx;
color: #333333;
}
.code-row {
display: flex;
align-items: center;
}
.code-row .input-field {
flex: 1;
}
.code-btn {
font-size: 26rpx;
color: #0088FF;
padding: 0 24rpx;
white-space: nowrap;
flex-shrink: 0;
}
.code-btn.disabled {
color: #cccccc;
}
/* 登录按钮 */
.login-btn {
height: 96rpx;
line-height: 96rpx;
text-align: center;
background-color: #0088FF;
color: #ffffff;
font-size: 32rpx;
font-weight: 500;
border-radius: 12rpx;
margin-bottom: 40rpx;
}
/* 协议区 */
.agreement-area {
display: flex;
align-items: center;
flex-wrap: wrap;
}
.checkbox {
width: 32rpx;
height: 32rpx;
border: 2rpx solid #0088FF;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
margin-right: 12rpx;
flex-shrink: 0;
}
.checkbox.checked {
background-color: #0088FF;
}
.check-icon {
font-size: 20rpx;
color: #ffffff;
}
.agreement-text {
font-size: 24rpx;
color: #999999;
}
.agreement-link {
font-size: 24rpx;
color: #0088FF;
}
/* xuchao: 顶部返回导航条(负外边距抵消页面左右 padding,通栏展示) */
.nav-bar {
display: flex;
align-items: center;
height: 44px;
background-color: #ffffff;
border-bottom: 1px solid #f0f0f0;
position: relative;
margin: 0 -40rpx;
}
.nav-back {
position: absolute;
left: 12px;
top: 0;
bottom: 0;
display: flex;
align-items: center;
}
.nav-title {
flex: 1;
text-align: center;
font-size: 17px;
font-weight: 500;
color: #1a1818;
padding: 0 56px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
</style>