添加找回密码功能
This commit is contained in:
1 parent
a4e01d96b8
commit
d0b5a3d582
2 files changed
+314
No files matched your search
@@ -37,3 +37,10 @@ export const login = (params) => {
|
|||||||
export const register = (params) => {
|
export const register = (params) => {
|
||||||
return get('/front/user/login/register', params);
|
return get('/front/user/login/register', params);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @desc 忘记密码
|
||||||
|
*/
|
||||||
|
export const forgetPassword = (params) => {
|
||||||
|
return post('/app-api/member/auth/password-reset', params);
|
||||||
|
};
|
||||||
@@ -0,0 +1,307 @@
|
|||||||
|
<script setup>
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import { forgetPassword, sendCodeToEmail } from './api';
|
||||||
|
|
||||||
|
// Password reset related variables
|
||||||
|
const email = ref('');
|
||||||
|
const newPassword = ref('');
|
||||||
|
const confirmPassword = ref('');
|
||||||
|
const verificationCode = ref('');
|
||||||
|
const codeBtnText = ref('Get Code');
|
||||||
|
const codeBtnDisabled = ref(false);
|
||||||
|
let countdownTimer = null;
|
||||||
|
|
||||||
|
// Email format validation
|
||||||
|
const validateEmail = (email) => {
|
||||||
|
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||||
|
return emailRegex.test(email);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get verification code
|
||||||
|
const getVerificationCode = async () => {
|
||||||
|
if (!email.value) {
|
||||||
|
uni.showToast({
|
||||||
|
title: 'Please enter email',
|
||||||
|
icon: 'none',
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!validateEmail(email.value)) {
|
||||||
|
uni.showToast({
|
||||||
|
title: 'Please enter a valid email',
|
||||||
|
icon: 'none',
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send verification code
|
||||||
|
try {
|
||||||
|
uni.showLoading({
|
||||||
|
title: 'Sending...',
|
||||||
|
mask: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const params = {
|
||||||
|
email: email.value,
|
||||||
|
register: false // Not for registration, but for password reset
|
||||||
|
};
|
||||||
|
|
||||||
|
const res = await sendCodeToEmail(params);
|
||||||
|
|
||||||
|
if (res && res.code === 0) {
|
||||||
|
uni.hideLoading();
|
||||||
|
uni.showToast({
|
||||||
|
title: 'Verification code sent',
|
||||||
|
icon: 'success',
|
||||||
|
});
|
||||||
|
|
||||||
|
// Start countdown
|
||||||
|
let timeLeft = 60;
|
||||||
|
codeBtnDisabled.value = true;
|
||||||
|
codeBtnText.value = `${timeLeft}s`;
|
||||||
|
|
||||||
|
countdownTimer = setInterval(() => {
|
||||||
|
timeLeft--;
|
||||||
|
codeBtnText.value = `${timeLeft}s`;
|
||||||
|
|
||||||
|
if (timeLeft <= 0) {
|
||||||
|
clearInterval(countdownTimer);
|
||||||
|
codeBtnText.value = 'Resend';
|
||||||
|
codeBtnDisabled.value = false;
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
} else {
|
||||||
|
uni.hideLoading();
|
||||||
|
uni.showToast({
|
||||||
|
title: res.msg || 'Send failed',
|
||||||
|
icon: 'error',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
uni.hideLoading();
|
||||||
|
uni.showToast({
|
||||||
|
title: error.message || 'Send failed, please try again',
|
||||||
|
icon: 'error',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Submit password reset
|
||||||
|
const onResetPassword = async () => {
|
||||||
|
if (!email.value) {
|
||||||
|
uni.showToast({
|
||||||
|
title: 'Please enter email',
|
||||||
|
icon: 'none',
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!validateEmail(email.value)) {
|
||||||
|
uni.showToast({
|
||||||
|
title: 'Please enter a valid email',
|
||||||
|
icon: 'none',
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!verificationCode.value) {
|
||||||
|
uni.showToast({
|
||||||
|
title: 'Please enter verification code',
|
||||||
|
icon: 'none',
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!newPassword.value) {
|
||||||
|
uni.showToast({
|
||||||
|
title: 'Please enter new password',
|
||||||
|
icon: 'none',
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newPassword.value !== confirmPassword.value) {
|
||||||
|
uni.showToast({
|
||||||
|
title: 'Passwords do not match',
|
||||||
|
icon: 'none',
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newPassword.value.length < 6) {
|
||||||
|
uni.showToast({
|
||||||
|
title: 'Password must be at least 6 characters',
|
||||||
|
icon: 'none',
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
uni.showLoading({
|
||||||
|
title: 'Resetting password...',
|
||||||
|
mask: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Call password reset API
|
||||||
|
const resetParams = {
|
||||||
|
email: email.value,
|
||||||
|
verificationCode: verificationCode.value,
|
||||||
|
password: newPassword.value,
|
||||||
|
confirmPassword: confirmPassword.value
|
||||||
|
};
|
||||||
|
|
||||||
|
const res = await forgetPassword(resetParams);
|
||||||
|
|
||||||
|
if (res && res.code === 0) {
|
||||||
|
uni.hideLoading();
|
||||||
|
uni.showToast({
|
||||||
|
title: 'Password reset successful',
|
||||||
|
icon: 'success',
|
||||||
|
});
|
||||||
|
|
||||||
|
// Navigate back to login page after success
|
||||||
|
setTimeout(() => {
|
||||||
|
uni.navigateBack();
|
||||||
|
}, 1500);
|
||||||
|
} else {
|
||||||
|
uni.hideLoading();
|
||||||
|
uni.showToast({
|
||||||
|
title: res.msg || 'Password reset failed',
|
||||||
|
icon: 'error',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
uni.hideLoading();
|
||||||
|
uni.showToast({
|
||||||
|
title: error.message || 'Password reset failed, please try again',
|
||||||
|
icon: 'error',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Clear input field
|
||||||
|
const clearInput = (type) => {
|
||||||
|
if (type === 'email') {
|
||||||
|
email.value = '';
|
||||||
|
} else if (type === 'newPassword') {
|
||||||
|
newPassword.value = '';
|
||||||
|
} else if (type === 'confirmPassword') {
|
||||||
|
confirmPassword.value = '';
|
||||||
|
} else if (type === 'verificationCode') {
|
||||||
|
verificationCode.value = '';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Go back to login page
|
||||||
|
const goLoginPage = function() {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: '/pages/login/index'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<view class="p-4 min-h-screen bg-white flex flex-col justify-center">
|
||||||
|
<!-- Title -->
|
||||||
|
<view class="mb-12 text-center">
|
||||||
|
<image src="/static/tabbar/find.png" class="w-20 h-20 mb-8" mode="aspectFit"></image>
|
||||||
|
<text class="block text-3xl font-bold text-gray-800 mb-4">RESET PASSWORD</text>
|
||||||
|
<text class="text-sm text-gray-500">Enter your email and new password</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- Email input -->
|
||||||
|
<view class="mb-6">
|
||||||
|
<view class=" flex items-center h-12 bg-gray-100 rounded-lg px-6 gap-1 border border-solid border-round-theme">
|
||||||
|
<u-icon name="email" class="h-10" color="black" bold="true"></u-icon>
|
||||||
|
<input
|
||||||
|
class="w-full text-base text-gray-800 bg-transparent"
|
||||||
|
type="email"
|
||||||
|
placeholder="Email Address"
|
||||||
|
v-model="email"
|
||||||
|
/>
|
||||||
|
<view
|
||||||
|
v-if="email"
|
||||||
|
class="absolute right-6 w-8 h-8 flex items-center justify-center bg-gray-400 rounded-full text-black font-bold"
|
||||||
|
@tap="clearInput('email')"
|
||||||
|
>
|
||||||
|
×
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- Verification code input -->
|
||||||
|
<view class="mb-6 relative">
|
||||||
|
<view class=" flex items-center h-12 bg-gray-100 rounded-lg px-6 gap-1 border border-solid border-round-theme">
|
||||||
|
<u-icon name="chat" class="h-10" color="black" bold="true"></u-icon>
|
||||||
|
<input
|
||||||
|
class="w-full text-base text-gray-800 bg-transparent pr-32"
|
||||||
|
type="text"
|
||||||
|
placeholder="Verification Code"
|
||||||
|
v-model="verificationCode"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
<button
|
||||||
|
class="absolute right-2 top-1/2 transform -translate-y-1/2 h-10 px-4 bg-theme text-white text-xs rounded-full disabled:bg-gray-400 disabled:text-gray-300 flex items-center justify-center"
|
||||||
|
:disabled="codeBtnDisabled"
|
||||||
|
@tap="getVerificationCode"
|
||||||
|
>
|
||||||
|
{{ codeBtnText }}
|
||||||
|
</button>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- New password input -->
|
||||||
|
<view class="mb-6">
|
||||||
|
<view class=" flex items-center h-12 bg-gray-100 rounded-lg px-6 gap-1 border border-solid border-round-theme">
|
||||||
|
<u-icon name="lock" class="h-10" color="black" bold="true"></u-icon>
|
||||||
|
<input
|
||||||
|
class="w-full text-base text-gray-800 bg-transparent"
|
||||||
|
type="password"
|
||||||
|
placeholder="New Password"
|
||||||
|
v-model="newPassword"
|
||||||
|
/>
|
||||||
|
<view
|
||||||
|
v-if="newPassword"
|
||||||
|
class="absolute right-6 w-8 h-8 flex items-center justify-center bg-gray-400 rounded-full text-white font-bold"
|
||||||
|
@tap="clearInput('newPassword')"
|
||||||
|
>
|
||||||
|
×
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- Confirm password input -->
|
||||||
|
<view class="mb-8">
|
||||||
|
<view class=" flex items-center h-12 bg-gray-100 rounded-lg px-6 gap-1 border border-solid border-round-theme">
|
||||||
|
<u-icon name="lock" class="h-10" color="black" bold="true"></u-icon>
|
||||||
|
<input
|
||||||
|
class="w-full text-base text-gray-800 bg-transparent"
|
||||||
|
type="password"
|
||||||
|
placeholder="Confirm Password"
|
||||||
|
v-model="confirmPassword"
|
||||||
|
/>
|
||||||
|
<view
|
||||||
|
v-if="confirmPassword"
|
||||||
|
class="absolute right-6 w-8 h-8 flex items-center justify-center bg-gray-400 rounded-full text-white font-bold"
|
||||||
|
@tap="clearInput('confirmPassword')"
|
||||||
|
>
|
||||||
|
×
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- Reset password button -->
|
||||||
|
<view
|
||||||
|
class="w-full h-12 bg-theme rounded-lg text-white text-xl flex items-center justify-center"
|
||||||
|
@click="onResetPassword"
|
||||||
|
>
|
||||||
|
<text>RESET PASSWORD</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- Back to login link -->
|
||||||
|
<view class="flex justify-center items-center my-8 text-gray-500 text-sm">
|
||||||
|
<text>Remember your password?</text>
|
||||||
|
<text class="text-green-500 ml-2" @click="goLoginPage">Back to Sign in</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
Reference in new issue
Block a user