You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
xukou-ticket-wx/pages/index/verify_backup_phone.vue

306 lines
7.1 KiB

<template>
<view class="verify-page">
<view class="fixed-nav" v-if="!isWeixinBrowser">
<NavBar title="验证备用手机号" />
</view>
<view class="content-area">
<view class="form-card">
<view class="form-title">备用手机号验证</view>
<view class="form-field">
<text class="form-label">备用手机号</text>
<input
class="form-input"
v-model="form.backup_phone"
type="number"
maxlength="11"
placeholder="请输入备用手机号"
/>
</view>
<view class="form-field">
<text class="form-label">验证码</text>
<view class="verify-code-row">
<input
class="form-input verify-code-input"
v-model="form.backup_phone_code"
type="number"
maxlength="6"
placeholder="请输入验证码"
/>
<button
class="send-code-btn"
:disabled="!canSendCode || countdown > 0"
@click="sendSmsCode"
>
{{ countdown > 0 ? countdown + '秒后重发' : '获取验证码' }}
</button>
</view>
</view>
</view>
<view class="submit-btn-wrapper">
<button class="submit-btn" @click="submitVerify"></button>
</view>
</view>
</view>
</template>
<script>
import NavBar from '@/components/NavBar.vue'
import { API } from '@/config/index.js'
export default {
name: 'VerifyBackupPhonePage',
components: { NavBar },
data() {
return {
isWeixinBrowser: false,
form: {
backup_phone: '',
backup_phone_code: ''
},
canSendCode: true,
countdown: 0,
countdownTimer: null
}
},
onLoad() {
// #ifdef H5
this.isWeixinBrowser = /MicroMessenger/i.test(navigator.userAgent)
// #endif
},
onUnload() {
// 清理倒计时定时器
if (this.countdownTimer) {
clearInterval(this.countdownTimer)
this.countdownTimer = null
}
},
methods: {
// 发送短信验证码
async sendSmsCode() {
// 验证手机号
const phoneReg = /^1\d{10}$/
if (!phoneReg.test(this.form.backup_phone)) {
uni.showToast({ title: '请输入正确的手机号', icon: 'none' })
return
}
if (!this.canSendCode || this.countdown > 0) {
return
}
const token = uni.getStorageSync('token')
if (!token) {
uni.showToast({ title: '请先登录', icon: 'none' })
return
}
try {
uni.showLoading({ title: '发送中...' })
const res = await new Promise((resolve, reject) => {
uni.request({
url: `${API.PROFILE_SEND_PHONE_CODE}?token=${token}`,
method: 'POST',
data: {
phone: this.form.backup_phone,
type: 'backup_phone'
},
success: resolve,
fail: reject
})
})
uni.hideLoading()
if (res.data && res.data.errcode === 0) {
uni.showToast({ title: '验证码已发送', icon: 'success' })
// 开始倒计时
this.canSendCode = false
this.countdown = 60
this.countdownTimer = setInterval(() => {
this.countdown--
if (this.countdown <= 0) {
clearInterval(this.countdownTimer)
this.countdownTimer = null
this.canSendCode = true
}
}, 1000)
} else {
uni.showToast({
title: (res.data && res.data.errmsg) || '发送失败',
icon: 'none'
})
}
} catch (e) {
uni.hideLoading()
uni.showToast({ title: '发送失败', icon: 'none' })
}
},
// 提交验证
async submitVerify() {
// 验证表单
const phoneReg = /^1\d{10}$/
if (!phoneReg.test(this.form.backup_phone)) {
uni.showToast({ title: '请输入正确的手机号', icon: 'none' })
return
}
if (!this.form.backup_phone_code || this.form.backup_phone_code.length !== 6) {
uni.showToast({ title: '请输入6位验证码', icon: 'none' })
return
}
const token = uni.getStorageSync('token')
if (!token) {
uni.showToast({ title: '请先登录', icon: 'none' })
return
}
try {
uni.showLoading({ title: '验证中...' })
const res = await new Promise((resolve, reject) => {
uni.request({
url: `${API.UPDATE_USER_INFO}?token=${token}`,
method: 'POST',
data: {
backup_phone: this.form.backup_phone,
backup_phone_code: this.form.backup_phone_code
},
success: resolve,
fail: reject
})
})
uni.hideLoading()
if (res.data && res.data.errcode === 0) {
uni.showToast({ title: '验证成功', icon: 'success' })
setTimeout(() => {
uni.navigateBack()
}, 1500)
} else {
uni.showToast({
title: (res.data && res.data.errmsg) || '验证失败',
icon: 'none'
})
}
} catch (e) {
uni.hideLoading()
uni.showToast({ title: '验证失败', icon: 'none' })
}
}
}
}
</script>
<style scoped>
.verify-page {
background: linear-gradient(180deg, #cbe6ff 0%, #f6faff 100%);
min-height: 100vh;
padding-bottom: 32rpx;
}
.wechat-browser {
padding-top: 10rpx;
}
.fixed-nav {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 100;
background: linear-gradient(180deg, #cbe6ff 0%, #f6faff 100%);
box-shadow: 0 2px 8px rgba(0,0,0,0.04);
}
.content-area {
padding-top: 90px;
padding-bottom: 20px;
}
.form-card {
background: #fff;
border-radius: 24rpx;
margin: 0 24rpx 32rpx 24rpx;
box-shadow: 0 4rpx 16rpx rgba(59,124,255,0.08);
padding: 32rpx 24rpx;
margin-top: 20px;
}
.form-title {
font-size: 32rpx;
font-weight: bold;
color: #222;
margin-bottom: 32rpx;
text-align: center;
}
.form-field {
margin-bottom: 32rpx;
}
.form-field:last-child {
margin-bottom: 0;
}
.form-label {
display: block;
font-size: 28rpx;
color: #666;
margin-bottom: 12rpx;
}
.form-input {
width: 100%;
height: 80rpx;
border-radius: 12rpx;
border: 1rpx solid #e5e6eb;
padding: 0 24rpx;
font-size: 28rpx;
box-sizing: border-box;
background: #fafafa;
}
.verify-code-row {
display: flex;
align-items: center;
gap: 16rpx;
}
.verify-code-input {
flex: 1;
}
.send-code-btn {
min-width: 180rpx;
height: 80rpx;
line-height: 80rpx;
border-radius: 12rpx;
background: #3b7cff;
color: #fff;
font-size: 24rpx;
border: none;
padding: 0 24rpx;
white-space: nowrap;
}
.send-code-btn::after {
border: none;
}
.send-code-btn:disabled {
background: #ccc;
color: #999;
}
.submit-btn-wrapper {
padding: 0 24rpx;
}
.submit-btn {
width: 100%;
height: 88rpx;
line-height: 88rpx;
border-radius: 44rpx;
background: linear-gradient(90deg, #3b7cff 0%, #5bb6ff 100%);
color: #fff;
font-size: 32rpx;
font-weight: 500;
border: none;
}
.submit-btn::after {
border: none;
}
</style>