357 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			Vue
		
	
	
	
			
		
		
	
	
			357 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			Vue
		
	
	
	
<template>
 | 
						|
	<page-meta :page-font-size="fontValue+'px'" :root-font-size="fontValue+'px'"></page-meta>
 | 
						|
  <view class="container">
 | 
						|
    <!-- 顶部导航栏 -->
 | 
						|
<!--    <view class="header">-->
 | 
						|
<!--      <view class="back-icon" @click="goBack">-->
 | 
						|
<!--        <image class="icon" :src="require('@/static/images/icons/back.png')" mode="aspectFit"></image>-->
 | 
						|
<!--      </view>-->
 | 
						|
<!--    </view>-->
 | 
						|
 | 
						|
    <!-- 主要内容区域 -->
 | 
						|
    <view class="content">
 | 
						|
      <view class="title-section">
 | 
						|
        <text class="title">输入6位验证码</text>
 | 
						|
        <text class="subtitle">验证码已发至 {{ formatPhone(phone) }}</text>
 | 
						|
      </view>
 | 
						|
 | 
						|
      <!-- 验证码输入框 -->
 | 
						|
      <view class="code-input-wrapper">
 | 
						|
        <input
 | 
						|
          v-for="(digit, index) in 6"
 | 
						|
          :key="index"
 | 
						|
          :ref="`codeInput${index}`"
 | 
						|
          v-model="verificationCode[index]"
 | 
						|
          type="number"
 | 
						|
          maxlength="1"
 | 
						|
          class="code-input"
 | 
						|
          :class="{ active: currentFocus === index }"
 | 
						|
          @input="handleInput($event, index)"
 | 
						|
          @focus="currentFocus = index"
 | 
						|
        />
 | 
						|
      </view>
 | 
						|
 | 
						|
      <!-- 重新获取验证码 -->
 | 
						|
      <view class="resend-wrapper" v-if="!showSuccessModal">
 | 
						|
        <text v-if="resendCountdown > 0" class="countdown">重新获取 {{ resendCountdown }}s</text>
 | 
						|
        <text v-else class="resend-btn" @click="handleResendCode">重新获取</text>
 | 
						|
      </view>
 | 
						|
 | 
						|
      <!-- 完成按钮 -->
 | 
						|
      <button
 | 
						|
        class="submit-btn"
 | 
						|
        :disabled="!isComplete"
 | 
						|
        @click="handleSubmit"
 | 
						|
      >
 | 
						|
        完成
 | 
						|
      </button>
 | 
						|
    </view>
 | 
						|
 | 
						|
    <!-- 成功弹窗 -->
 | 
						|
    <view class="modal" v-if="showSuccessModal">
 | 
						|
      <view class="modal-content">
 | 
						|
        <view class="success-icon">
 | 
						|
          <image class="icon" :src="require('@/static/images/my/success.png')" mode="aspectFit"></image>
 | 
						|
        </view>
 | 
						|
        <text class="success-title">手机号更新成功</text>
 | 
						|
        <text class="success-subtitle">{{ redirectCountdown }}秒后自动返回界面</text>
 | 
						|
        <text class="relogin-btn" @click="handleRelogin">重新登录</text>
 | 
						|
      </view>
 | 
						|
    </view>
 | 
						|
  </view>
 | 
						|
</template>
 | 
						|
 | 
						|
<script>
 | 
						|
import { getTextCode } from '@/api/login';
 | 
						|
import { rebindMobileApi } from '@/api/mine/index.js';
 | 
						|
 | 
						|
export default {
 | 
						|
  data() {
 | 
						|
    return {
 | 
						|
		fontValue:uni.getStorageSync('fontSize') || 8,
 | 
						|
      phone: '',
 | 
						|
      verificationCode: ['', '', '', '', '', ''],
 | 
						|
      currentFocus: 0,
 | 
						|
      resendCountdown: 60,
 | 
						|
      redirectCountdown: 5,
 | 
						|
      resendTimer: null,
 | 
						|
      redirectTimer: null,
 | 
						|
      showSuccessModal: false
 | 
						|
    }
 | 
						|
  },
 | 
						|
  computed: {
 | 
						|
    isComplete() {
 | 
						|
      return this.verificationCode.every(digit => digit !== '')
 | 
						|
    }
 | 
						|
  },
 | 
						|
  onLoad(options) {
 | 
						|
    this.phone = options.phone || ''
 | 
						|
	this.getCode()
 | 
						|
    this.startResendCountdown()
 | 
						|
  },
 | 
						|
  onUnload() {
 | 
						|
    this.clearTimers()
 | 
						|
  },
 | 
						|
  methods: {
 | 
						|
	  //获取验证码
 | 
						|
	  getCode(){
 | 
						|
		  let param = {
 | 
						|
		  		"username": this.phone,
 | 
						|
		  		"verificationCodeType": "LOGIN"
 | 
						|
		  }
 | 
						|
		  getTextCode(param).then(res => {
 | 
						|
		    if(res.code==200){
 | 
						|
				uni.$u.toast('验证码已发送')
 | 
						|
			}
 | 
						|
		  })
 | 
						|
	  },
 | 
						|
    formatPhone(phone) {
 | 
						|
      if (!phone) return ''
 | 
						|
      return phone.replace(/(\d{3})(\d{4})(\d{4})/, '$1 $2 $3')
 | 
						|
    },
 | 
						|
    goBack() {
 | 
						|
      uni.navigateBack()
 | 
						|
    },
 | 
						|
    handleInput(event, index) {
 | 
						|
      const value = event.detail.value
 | 
						|
      // Ensure the input is a single digit
 | 
						|
      this.verificationCode[index] = value.slice(0, 1)
 | 
						|
 | 
						|
      // Move to next input if a digit was entered and it's not the last input
 | 
						|
      if (value && index < 5) {
 | 
						|
        this.$nextTick(() => {
 | 
						|
          // Focus the next input
 | 
						|
          const nextInput = this.$refs[`codeInput${index + 1}`][0]
 | 
						|
          if (nextInput && typeof nextInput.focus === 'function') {
 | 
						|
            nextInput.focus()
 | 
						|
          }
 | 
						|
        })
 | 
						|
      }
 | 
						|
    },
 | 
						|
    startResendCountdown() {
 | 
						|
      this.clearTimers()
 | 
						|
      this.resendTimer = setInterval(() => {
 | 
						|
        if (this.resendCountdown > 0) {
 | 
						|
          this.resendCountdown--
 | 
						|
        } else {
 | 
						|
          clearInterval(this.resendTimer)
 | 
						|
          this.resendTimer = null
 | 
						|
        }
 | 
						|
      }, 1000)
 | 
						|
    },
 | 
						|
    startRedirectCountdown() {
 | 
						|
      this.redirectTimer = setInterval(() => {
 | 
						|
        if (this.redirectCountdown > 0) {
 | 
						|
          this.redirectCountdown--
 | 
						|
        } else {
 | 
						|
          clearInterval(this.redirectTimer)
 | 
						|
          this.redirectTimer = null
 | 
						|
          this.handleRelogin()
 | 
						|
        }
 | 
						|
      }, 1000)
 | 
						|
    },
 | 
						|
    clearTimers() {
 | 
						|
      if (this.resendTimer) {
 | 
						|
        clearInterval(this.resendTimer)
 | 
						|
        this.resendTimer = null
 | 
						|
      }
 | 
						|
      if (this.redirectTimer) {
 | 
						|
        clearInterval(this.redirectTimer)
 | 
						|
        this.redirectTimer = null
 | 
						|
      }
 | 
						|
    },
 | 
						|
    handleResendCode() {
 | 
						|
      if (this.resendCountdown > 0) return
 | 
						|
      this.resendCountdown = 60
 | 
						|
      this.startResendCountdown()
 | 
						|
	  this.getCode()
 | 
						|
      // 这里添加重新发送验证码的逻辑
 | 
						|
    },
 | 
						|
    async handleSubmit() {
 | 
						|
      if (!this.isComplete) return 
 | 
						|
	  
 | 
						|
	  let param = {
 | 
						|
		"oldMobile": getStorageSync('username') ,
 | 
						|
		"newMobile": this.phone,
 | 
						|
		"code": this.verificationCode.join("")
 | 
						|
	  }
 | 
						|
	  console.log(param) 
 | 
						|
	  const res = await rebindMobileApi(param)
 | 
						|
	  if(res.code==200){
 | 
						|
		  // 显示成功弹窗并开始重定向倒计时
 | 
						|
		  this.showSuccessModal = true
 | 
						|
		  this.redirectCountdown = 5
 | 
						|
		  this.startRedirectCountdown()
 | 
						|
	  }else{
 | 
						|
		  uni.showToast({
 | 
						|
		  	title: res.msg,
 | 
						|
		  	icon: 'none'
 | 
						|
		  });
 | 
						|
	  }
 | 
						|
    },
 | 
						|
    handleRelogin() {
 | 
						|
      // 这里添加重新登录的逻辑
 | 
						|
      uni.reLaunch({
 | 
						|
        url: '/pages/login'
 | 
						|
      })
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
</script>
 | 
						|
 | 
						|
<style lang="scss">
 | 
						|
.container {
 | 
						|
  min-height: 100vh;
 | 
						|
  background-color: #fff;
 | 
						|
}
 | 
						|
 | 
						|
.header {
 | 
						|
  padding: 44px 32rpx 0;
 | 
						|
  height: 88rpx;
 | 
						|
  display: flex;
 | 
						|
  align-items: center;
 | 
						|
 | 
						|
  .back-icon {
 | 
						|
    padding: 20rpx;
 | 
						|
    margin-left: -20rpx;
 | 
						|
 | 
						|
    .icon {
 | 
						|
      width: 40rpx;
 | 
						|
      height: 40rpx;
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
.content {
 | 
						|
  padding: 32rpx;
 | 
						|
}
 | 
						|
 | 
						|
.title-section {
 | 
						|
  margin-bottom: 48rpx;
 | 
						|
 | 
						|
  .title {
 | 
						|
    font-size: 40rpx;
 | 
						|
    font-weight: 500;
 | 
						|
    color: #333;
 | 
						|
    margin-bottom: 16rpx;
 | 
						|
    display: block;
 | 
						|
  }
 | 
						|
 | 
						|
  .subtitle {
 | 
						|
    font-size: 28rpx;
 | 
						|
    color: #999;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
.code-input-wrapper {
 | 
						|
  display: flex;
 | 
						|
  justify-content: space-between;
 | 
						|
  margin-bottom: 32rpx;
 | 
						|
 | 
						|
  .code-input {
 | 
						|
    width: 80rpx;
 | 
						|
    height: 80rpx;
 | 
						|
    background: #F5F5F5;
 | 
						|
    border-radius: 16rpx;
 | 
						|
    text-align: center;
 | 
						|
    font-size: 40rpx;
 | 
						|
    color: #333;
 | 
						|
 | 
						|
    &.active {
 | 
						|
      background: #fff;
 | 
						|
      border: 2rpx solid #FF8126;
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
.resend-wrapper {
 | 
						|
  text-align: center;
 | 
						|
  margin-bottom: 48rpx;
 | 
						|
 | 
						|
  .countdown {
 | 
						|
    font-size: 28rpx;
 | 
						|
    color: #999;
 | 
						|
  }
 | 
						|
 | 
						|
  .resend-btn {
 | 
						|
    font-size: 28rpx;
 | 
						|
    color: #FF8126;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
.submit-btn {
 | 
						|
  width: 100%;
 | 
						|
  height: 88rpx;
 | 
						|
  background: #FF8126;
 | 
						|
  color: #fff;
 | 
						|
  font-size: 32rpx;
 | 
						|
  font-weight: 500;
 | 
						|
  border-radius: 44rpx;
 | 
						|
  display: flex;
 | 
						|
  align-items: center;
 | 
						|
  justify-content: center;
 | 
						|
  border: none;
 | 
						|
 | 
						|
  &:disabled {
 | 
						|
    opacity: 0.5;
 | 
						|
  }
 | 
						|
 | 
						|
  &:active {
 | 
						|
    opacity: 0.9;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
.modal {
 | 
						|
  position: fixed;
 | 
						|
  top: 0;
 | 
						|
  left: 0;
 | 
						|
  right: 0;
 | 
						|
  bottom: 0;
 | 
						|
  background: rgba(0, 0, 0, 0.5);
 | 
						|
  display: flex;
 | 
						|
  align-items: center;
 | 
						|
  justify-content: center;
 | 
						|
  z-index: 1000;
 | 
						|
 | 
						|
  .modal-content {
 | 
						|
    width: 560rpx;
 | 
						|
    background: #fff;
 | 
						|
    border-radius: 24rpx;
 | 
						|
    padding: 48rpx;
 | 
						|
    display: flex;
 | 
						|
    flex-direction: column;
 | 
						|
    align-items: center;
 | 
						|
 | 
						|
    .success-icon {
 | 
						|
      width: 120rpx;
 | 
						|
      height: 120rpx;
 | 
						|
      margin-bottom: 32rpx;
 | 
						|
 | 
						|
      .icon {
 | 
						|
        width: 100%;
 | 
						|
        height: 100%;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    .success-title {
 | 
						|
      font-size: 32rpx;
 | 
						|
      font-weight: 500;
 | 
						|
      color: #333;
 | 
						|
      margin-bottom: 16rpx;
 | 
						|
    }
 | 
						|
 | 
						|
    .success-subtitle {
 | 
						|
      font-size: 28rpx;
 | 
						|
      color: #999;
 | 
						|
      margin-bottom: 32rpx;
 | 
						|
    }
 | 
						|
 | 
						|
    .relogin-btn {
 | 
						|
      font-size: 28rpx;
 | 
						|
      color: #FF8126;
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
</style>
 | 
						|
 |