Files
medical-mall/pages/user/forgot-password.uvue

322 lines
6.7 KiB
Plaintext

<template>
<scroll-view class="forgot-password-container" scroll-y="true" show-scrollbar="false">
<view class="language-switch">
<button class="language-btn" @click="toggleLanguage">
{{ currentLocale === 'zh-CN' ? 'EN' : '中' }}
</button>
</view>
<view class="content-wrapper">
<view class="logo-section">
<text class="app-title">Akmon</text>
<text class="page-title">忘记密码</text>
<text class="page-subtitle">输入您的邮箱地址,我们将发送重置链接</text>
</view>
<view class="form-container">
<view v-if="resetEmailSent == false">
<form @submit="onSubmit">
<view class="input-group" :class="emailError != '' ? 'input-error' : ''">
<text class="input-label">邮箱</text>
<input
class="input-field"
name="email"
type="text"
v-model="email"
placeholder="请输入邮箱地址"
@blur="validateEmail"
/>
<text v-if="emailError != ''" class="error-text">{{ emailError }}</text>
</view>
<button form-type="submit" class="submit-button" :disabled="isLoading" :loading="isLoading">
发送重置链接
</button>
<text v-if="generalError != ''" class="general-error">{{ generalError }}</text>
</form>
<view class="login-option">
<text class="login-text">想起密码了?</text>
<text class="login-link" @click="navigateToLogin">返回登录</text>
</view>
</view>
<view v-else class="success-container">
<view class="success-icon">✓</view>
<text class="success-title">邮件已发送</text>
<text class="success-message">请检查您的邮箱,按照邮件中的说明重置密码</text>
<button class="back-button" @click="navigateToLogin">
返回登录
</button>
</view>
</view>
</view>
</scroll-view>
</template>
<script setup lang="uts">
import { ref } from 'vue'
const email = ref<string>('')
const emailError = ref<string>('')
const generalError = ref<string>('')
const isLoading = ref<boolean>(false)
const resetEmailSent = ref<boolean>(false)
const currentLocale = ref<string>('zh-CN')
const toggleLanguage = (): void => {
if (currentLocale.value === 'zh-CN') {
currentLocale.value = 'en-US'
} else {
currentLocale.value = 'zh-CN'
}
uni.showToast({
title: '语言已切换',
icon: 'success'
})
}
const validateEmail = (): boolean => {
if (email.value == null || email.value == '') {
emailError.value = '请输入邮箱地址'
return false
}
const atIndex = email.value.indexOf('@')
const dotIndex = email.value.lastIndexOf('.')
if (atIndex == -1 || dotIndex == -1 || atIndex > dotIndex) {
emailError.value = '请输入有效的邮箱地址'
return false
}
emailError.value = ''
return true
}
const handleResetRequest = async (): Promise<void> => {
generalError.value = ''
if (validateEmail() == false) {
return
}
isLoading.value = true
try {
resetEmailSent.value = true
} catch (err) {
console.error("Password reset error:", err)
generalError.value = '发送失败,请稍后重试'
} finally {
isLoading.value = false
}
}
const onSubmit = (e: UniFormSubmitEvent): void => {
handleResetRequest()
}
const navigateToLogin = (): void => {
uni.navigateTo({
url: '/pages/user/login'
})
}
</script>
<style>
.forgot-password-container {
height: 100%;
padding: 40rpx;
background-color: #f8f9fa;
box-sizing: border-box;
}
.content-wrapper {
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-start;
padding-bottom: 40rpx;
min-height: 800rpx;
}
.language-switch {
position: absolute;
top: 40rpx;
right: 40rpx;
z-index: 10;
}
.language-btn {
width: 80rpx;
height: 80rpx;
border-radius: 40rpx;
font-size: 28rpx;
background-color: rgba(33, 150, 243, 0.8);
color: #fff;
font-weight: normal;
border: 2rpx solid rgba(255, 255, 255, 0.3);
text-align: center;
box-shadow: 0 4rpx 12rpx rgba(33, 150, 243, 0.3);
}
.logo-section {
display: flex;
flex-direction: column;
align-items: center;
margin-top: 80rpx;
margin-bottom: 40rpx;
}
.app-title {
font-size: 36rpx;
font-weight: bold;
color: #2196f3;
}
.page-title {
font-size: 48rpx;
margin-top: 20rpx;
font-weight: bold;
color: #333;
}
.page-subtitle {
font-size: 28rpx;
margin-top: 10rpx;
color: #666;
}
.form-container {
width: 100%;
max-width: 680rpx;
padding: 40rpx;
background-color: #ffffff;
border-radius: 20rpx;
box-shadow: 0 10rpx 30rpx rgba(0, 0, 0, 0.1);
box-sizing: border-box;
}
.input-group {
margin-bottom: 30rpx;
}
.input-label {
font-size: 28rpx;
margin-bottom: 10rpx;
font-weight: normal;
color: #333;
display: flex;
}
.input-field {
width: 100%;
height: 90rpx;
padding: 0 30rpx;
font-size: 28rpx;
border-radius: 10rpx;
border: 2rpx solid #ddd;
background-color: #f9f9f9;
box-sizing: border-box;
}
.input-error .input-field {
border-color: #f44336;
}
.error-text {
font-size: 24rpx;
margin-top: 6rpx;
color: #f44336;
}
.submit-button {
width: 100%;
height: 90rpx;
font-size: 32rpx;
margin: 20rpx 0;
border-radius: 45rpx;
background-image: linear-gradient(to right, #2196f3, #03a9f4);
color: #fff;
font-weight: normal;
text-align: center;
box-shadow: 0 10rpx 20rpx rgba(3, 169, 244, 0.2);
}
.submit-button:disabled {
background: #ccc;
box-shadow: none;
}
.general-error {
width: 100%;
text-align: center;
color: #f44336;
font-size: 28rpx;
margin-top: 20rpx;
}
.login-option {
display: flex;
justify-content: center;
margin-top: 40rpx;
}
.login-text {
font-size: 28rpx;
margin-right: 8rpx;
color: #666;
}
.login-link {
font-size: 28rpx;
color: #2196f3;
font-weight: normal;
}
.success-container {
display: flex;
flex-direction: column;
align-items: center;
padding: 20rpx 0;
}
.success-icon {
width: 120rpx;
height: 120rpx;
font-size: 60rpx;
margin-bottom: 30rpx;
background-color: #4caf50;
color: white;
border-radius: 120rpx;
display: flex;
align-items: center;
justify-content: center;
}
.success-title {
font-size: 36rpx;
margin-bottom: 20rpx;
font-weight: bold;
color: #333;
}
.success-message {
font-size: 28rpx;
margin-bottom: 40rpx;
color: #666;
text-align: center;
}
.back-button {
width: 100%;
height: 90rpx;
font-size: 32rpx;
border-radius: 45rpx;
background-color: #f0f0f0;
color: #333;
font-weight: normal;
text-align: center;
}
</style>