|
@@ -0,0 +1,291 @@
|
|
|
|
+<route lang="json5" type="page">
|
|
|
|
+{
|
|
|
|
+ layout: 'default',
|
|
|
|
+ style: {
|
|
|
|
+ navigationStyle: 'custom',
|
|
|
|
+ },
|
|
|
|
+}
|
|
|
|
+</route>
|
|
|
|
+
|
|
|
|
+<script lang="ts" setup>
|
|
|
|
+// 必须导入需要用到的页面生命周期(即使在当前页面上没有直接使用到)
|
|
|
|
+// eslint-disable-next-line unused-imports/no-unused-imports
|
|
|
|
+import { onPageScroll, onReachBottom } from '@dcloudio/uni-app'
|
|
|
|
+
|
|
|
|
+defineOptions({
|
|
|
|
+ name: 'ForgotPassword', // 忘记密码
|
|
|
|
+})
|
|
|
|
+
|
|
|
|
+// 获取屏幕边界到安全区域距离
|
|
|
|
+const systemInfo = uni.getSystemInfoSync()
|
|
|
|
+const safeAreaInsets = systemInfo.safeAreaInsets
|
|
|
|
+
|
|
|
|
+// 步骤控制:1-输入手机号,2-重置密码
|
|
|
|
+const step = ref(1)
|
|
|
|
+
|
|
|
|
+// 表单数据
|
|
|
|
+const formData = ref({
|
|
|
|
+ mobile: '',
|
|
|
|
+ verificationCode: '',
|
|
|
|
+ newPassword: '',
|
|
|
|
+ confirmPassword: '',
|
|
|
|
+})
|
|
|
|
+
|
|
|
|
+// 验证码倒计时
|
|
|
|
+const countdown = ref(0)
|
|
|
|
+const countdownTimer = ref<NodeJS.Timeout | null>(null)
|
|
|
|
+
|
|
|
|
+// 表单验证规则
|
|
|
|
+const rules = {
|
|
|
|
+ mobile: [
|
|
|
|
+ { required: true, message: 'Please enter mobile number' },
|
|
|
|
+ { pattern: /^1[3-9]\d{9}$/, message: 'Please enter valid mobile number' },
|
|
|
|
+ ],
|
|
|
|
+ verificationCode: [
|
|
|
|
+ { required: true, message: 'Please enter verification code' },
|
|
|
|
+ ],
|
|
|
|
+ newPassword: [
|
|
|
|
+ { required: true, message: 'Please enter new password' },
|
|
|
|
+ { min: 6, max: 20, message: 'Password should be 6-20 characters' },
|
|
|
|
+ ],
|
|
|
|
+ confirmPassword: [
|
|
|
|
+ { required: true, message: 'Please confirm password' },
|
|
|
|
+ {
|
|
|
|
+ validator: (value: string) => {
|
|
|
|
+ return value === formData.value.newPassword
|
|
|
|
+ },
|
|
|
|
+ message: 'Passwords do not match',
|
|
|
|
+ },
|
|
|
|
+ ],
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// 获取验证码
|
|
|
|
+function getVerificationCode() {
|
|
|
|
+ if (!formData.value.mobile) {
|
|
|
|
+ uni.showToast({
|
|
|
|
+ title: 'Please enter mobile number first',
|
|
|
|
+ icon: 'none',
|
|
|
|
+ })
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // TODO: 实现获取验证码逻辑
|
|
|
|
+ console.log('Get verification code for:', formData.value.mobile)
|
|
|
|
+
|
|
|
|
+ // 开始倒计时
|
|
|
|
+ countdown.value = 60
|
|
|
|
+ countdownTimer.value = setInterval(() => {
|
|
|
|
+ countdown.value--
|
|
|
|
+ if (countdown.value <= 0) {
|
|
|
|
+ clearInterval(countdownTimer.value!)
|
|
|
|
+ countdownTimer.value = null
|
|
|
|
+ }
|
|
|
|
+ }, 1000)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// 第一步:验证手机号
|
|
|
|
+function handleStep1() {
|
|
|
|
+ if (!formData.value.mobile) {
|
|
|
|
+ uni.showToast({
|
|
|
|
+ title: 'Please enter mobile number',
|
|
|
|
+ icon: 'none',
|
|
|
|
+ })
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // TODO: 验证手机号逻辑
|
|
|
|
+ console.log('Verify mobile:', formData.value.mobile)
|
|
|
|
+
|
|
|
|
+ // 跳转到第二步
|
|
|
|
+ step.value = 2
|
|
|
|
+ // 预填手机号
|
|
|
|
+ formData.value.mobile = '88016266123'
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// 第二步:重置密码
|
|
|
|
+function handleResetPassword() {
|
|
|
|
+ if (!formData.value.verificationCode || !formData.value.newPassword || !formData.value.confirmPassword) {
|
|
|
|
+ uni.showToast({
|
|
|
|
+ title: 'Please fill in all fields',
|
|
|
|
+ icon: 'none',
|
|
|
|
+ })
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (formData.value.newPassword !== formData.value.confirmPassword) {
|
|
|
|
+ uni.showToast({
|
|
|
|
+ title: 'Passwords do not match',
|
|
|
|
+ icon: 'none',
|
|
|
|
+ })
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // TODO: 实现重置密码逻辑
|
|
|
|
+ console.log('Reset password:', formData.value)
|
|
|
|
+
|
|
|
|
+ uni.showToast({
|
|
|
|
+ title: 'Password reset successfully',
|
|
|
|
+ icon: 'success',
|
|
|
|
+ })
|
|
|
|
+
|
|
|
|
+ // 跳转到登录页
|
|
|
|
+ setTimeout(() => {
|
|
|
|
+ uni.redirectTo({
|
|
|
|
+ url: '/pages/login/login',
|
|
|
|
+ })
|
|
|
|
+ }, 1500)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// 跳转登录页
|
|
|
|
+function toLogin() {
|
|
|
|
+ uni.navigateTo({
|
|
|
|
+ url: '/pages/login/login',
|
|
|
|
+ })
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// 返回上一页
|
|
|
|
+function goBack() {
|
|
|
|
+ if (step.value === 2) {
|
|
|
|
+ step.value = 1
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
|
|
+ uni.navigateBack()
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// 页面卸载时清理定时器
|
|
|
|
+onUnmounted(() => {
|
|
|
|
+ if (countdownTimer.value) {
|
|
|
|
+ clearInterval(countdownTimer.value)
|
|
|
|
+ }
|
|
|
|
+})
|
|
|
|
+</script>
|
|
|
|
+
|
|
|
|
+<template>
|
|
|
|
+ <view class="forgot-password-page min-h-screen bg-white">
|
|
|
|
+ <!-- 背景图片区域 -->
|
|
|
|
+ <view class="auth-bg-section relative">
|
|
|
|
+ <!-- 自定义导航栏 -->
|
|
|
|
+ <view :style="{ paddingTop: `${safeAreaInsets?.top}px` }">
|
|
|
|
+ <view class="h-88rpx flex items-center px-24rpx">
|
|
|
|
+ <wd-icon name="arrow-left" size="48rpx" color="#333" @click="goBack" />
|
|
|
|
+ </view>
|
|
|
|
+ </view>
|
|
|
|
+
|
|
|
|
+ <!-- Logo和标语 -->
|
|
|
|
+ <view class="pb-60rpx pt-60rpx text-center">
|
|
|
|
+ <view class="mb-20rpx flex items-center justify-center">
|
|
|
|
+ <image src="/static/logo.png" class="mr-16rpx h-60rpx w-60rpx" />
|
|
|
|
+ </view>
|
|
|
|
+ </view>
|
|
|
|
+ </view>
|
|
|
|
+
|
|
|
|
+ <!-- 表单内容区域 -->
|
|
|
|
+ <view class="flex flex-col px-20rpx">
|
|
|
|
+ <view class="mb-40rpx" />
|
|
|
|
+
|
|
|
|
+ <!-- 第一步:输入手机号 -->
|
|
|
|
+ <view v-if="step === 1">
|
|
|
|
+ <wd-form ref="form" :model="formData" :rules="rules">
|
|
|
|
+ <view class="mb-60rpx">
|
|
|
|
+ <wd-input
|
|
|
|
+ v-model="formData.mobile"
|
|
|
|
+ prop="mobile"
|
|
|
|
+ placeholder="+88 Mobile number"
|
|
|
|
+ no-border
|
|
|
|
+ custom-class="bandhu-auth-input-field"
|
|
|
|
+ />
|
|
|
|
+ </view>
|
|
|
|
+
|
|
|
|
+ <!-- 重置密码按钮 -->
|
|
|
|
+ <wd-button
|
|
|
|
+ type="error"
|
|
|
|
+ size="large"
|
|
|
|
+ custom-class="mb-200rpx w-full bandhu-auth-primary-btn"
|
|
|
|
+ @click="handleStep1"
|
|
|
|
+ >
|
|
|
|
+ Reset Password
|
|
|
|
+ </wd-button>
|
|
|
|
+ </wd-form>
|
|
|
|
+ </view>
|
|
|
|
+
|
|
|
|
+ <!-- 第二步:重置密码 -->
|
|
|
|
+ <view v-else>
|
|
|
|
+ <wd-form ref="form" :model="formData" :rules="rules">
|
|
|
|
+ <view class="mb-40rpx space-y-32rpx">
|
|
|
|
+ <wd-input
|
|
|
|
+ v-model="formData.mobile"
|
|
|
|
+ prop="mobile"
|
|
|
|
+
|
|
|
|
+ no-border disabled
|
|
|
|
+ custom-class="bandhu-auth-input-field"
|
|
|
|
+ />
|
|
|
|
+ <view class="flex items-center gap-20rpx">
|
|
|
|
+ <wd-input
|
|
|
|
+ v-model="formData.verificationCode"
|
|
|
|
+ prop="verificationCode"
|
|
|
|
+ placeholder="Verification Code"
|
|
|
|
+ no-border
|
|
|
|
+ custom-class="flex-1 bandhu-auth-input-field"
|
|
|
|
+ />
|
|
|
|
+ <wd-button
|
|
|
|
+ type="error"
|
|
|
|
+ plain
|
|
|
|
+ :disabled="countdown > 0"
|
|
|
|
+ custom-class="bandhu-auth-secondary-btn"
|
|
|
|
+ @click="getVerificationCode"
|
|
|
|
+ >
|
|
|
|
+ {{ countdown > 0 ? `${countdown}s` : 'Get Code' }}
|
|
|
|
+ </wd-button>
|
|
|
|
+ </view>
|
|
|
|
+ <wd-input
|
|
|
|
+ v-model="formData.newPassword"
|
|
|
|
+ prop="newPassword"
|
|
|
|
+ show-password
|
|
|
|
+ placeholder="New Password 6-20 characters"
|
|
|
|
+ no-border
|
|
|
|
+ custom-class="bandhu-auth-input-field"
|
|
|
|
+ />
|
|
|
|
+ <wd-input
|
|
|
|
+ v-model="formData.confirmPassword"
|
|
|
|
+ prop="confirmPassword"
|
|
|
|
+ show-password
|
|
|
|
+ placeholder="Confirm password"
|
|
|
|
+ no-border
|
|
|
|
+ custom-class="bandhu-auth-input-field"
|
|
|
|
+ />
|
|
|
|
+ </view>
|
|
|
|
+
|
|
|
|
+ <!-- 密码提示 -->
|
|
|
|
+ <view class="mb-60rpx text-center text-24rpx text-#666">
|
|
|
|
+ Your password must be different from previous used password
|
|
|
|
+ </view>
|
|
|
|
+
|
|
|
|
+ <!-- 重置密码按钮 -->
|
|
|
|
+ <wd-button
|
|
|
|
+ type="error"
|
|
|
|
+ size="large"
|
|
|
|
+ custom-class="mb-200rpx w-full bandhu-auth-primary-btn"
|
|
|
|
+ @click="handleResetPassword"
|
|
|
|
+ >
|
|
|
|
+ Reset Password
|
|
|
|
+ </wd-button>
|
|
|
|
+ </wd-form>
|
|
|
|
+ </view>
|
|
|
|
+
|
|
|
|
+ <!-- 登录提示 -->
|
|
|
|
+ <view class="text-center">
|
|
|
|
+ <text class="text-28rpx text-#666">
|
|
|
|
+ Already have account?
|
|
|
|
+ </text>
|
|
|
|
+ <text class="text-28rpx text-[var(--wot-color-theme)]" @click="toLogin">
|
|
|
|
+ Login Now
|
|
|
|
+ </text>
|
|
|
|
+ </view>
|
|
|
|
+ </view>
|
|
|
|
+ </view>
|
|
|
|
+</template>
|
|
|
|
+
|
|
|
|
+<style lang="scss" scoped>
|
|
|
|
+// 忘记密码页面特有样式(如果有的话)
|
|
|
|
+</style>
|