Files
vueadmin/src/pages/login/resetPassword.vue
2026-01-15 23:23:37 +08:00

211 lines
4.8 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div class="login-container">
<div class="login-wrapper">
<div class="login-card">
<div class="login-header">
<div class="login-logo">
<h1>Vue Admin</h1>
</div>
<p class="login-subtitle">重置密码</p>
</div>
<a-form :model="formState" @finish="handleReset" layout="vertical" class="login-form">
<a-form-item name="email" :rules="[
{ required: true, message: '请输入邮箱' },
{ type: 'email', message: '请输入有效的邮箱地址' },
]">
<a-input v-model:value="formState.email" placeholder="邮箱地址" size="large"
:prefix="h(MailOutlined)" />
</a-form-item>
<a-form-item name="verificationCode" :rules="[{ required: true, message: '请输入验证码' }]">
<a-input v-model:value="formState.verificationCode" placeholder="验证码" size="large"
:prefix="h(SafetyOutlined)">
<template #suffix>
<a-button type="link" :disabled="countdown > 0" @click="sendCode" class="code-btn">
{{ countdown > 0 ? `${countdown}秒后重试` : '发送验证码' }}
</a-button>
</template>
</a-input>
</a-form-item>
<a-form-item name="newPassword" :rules="[
{ required: true, message: '请输入新密码' },
{ min: 6, message: '密码至少6个字符' },
]">
<a-input-password v-model:value="formState.newPassword" placeholder="新密码" size="large"
:prefix="h(LockOutlined)" />
</a-form-item>
<a-form-item name="confirmPassword" :rules="[
{ required: true, message: '请确认新密码' },
{ validator: validateConfirmPassword },
]">
<a-input-password v-model:value="formState.confirmPassword" placeholder="确认新密码" size="large"
:prefix="h(LockOutlined)" />
</a-form-item>
<a-form-item>
<a-button type="primary" html-type="submit" size="large" block :loading="loading">
重置密码
</a-button>
</a-form-item>
<div class="form-footer">
<span>记得密码了</span>
<router-link to="/login" class="register-link">
立即登录
</router-link>
</div>
</a-form>
</div>
</div>
</div>
</template>
<script setup>
import { reactive, ref, h } from 'vue';
import { useRouter } from 'vue-router';
import { message } from 'ant-design-vue';
import {
MailOutlined,
SafetyOutlined,
LockOutlined,
} from '@ant-design/icons-vue';
// 定义组件名称(多词命名)
defineOptions({
name: 'ResetPasswordPage'
});
const router = useRouter();
const loading = ref(false);
const countdown = ref(0);
const formState = reactive({
email: '',
verificationCode: '',
newPassword: '',
confirmPassword: '',
});
const validateConfirmPassword = async (rule, value) => {
if (value !== formState.newPassword) {
return Promise.reject('两次输入的密码不一致');
}
return Promise.resolve();
};
const sendCode = () => {
if (!formState.email) {
message.warning('请先输入邮箱地址');
return;
}
// TODO: 实现发送验证码逻辑
message.success('验证码已发送');
countdown.value = 60;
const timer = setInterval(() => {
countdown.value--;
if (countdown.value <= 0) {
clearInterval(timer);
}
}, 1000);
};
const handleReset = async () => {
loading.value = true;
try {
// TODO: 实现重置密码逻辑
await new Promise((resolve) => setTimeout(resolve, 1000));
message.success('密码重置成功,请登录');
router.push('/login');
} catch {
message.error('密码重置失败,请稍后重试');
} finally {
loading.value = false;
}
};
</script>
<style scoped>
.login-container {
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
padding: 20px;
}
.login-wrapper {
width: 100%;
max-width: 400px;
}
.login-card {
background: white;
border-radius: 16px;
padding: 40px;
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.1);
}
.login-header {
text-align: center;
margin-bottom: 32px;
}
.login-logo h1 {
margin: 0;
font-size: 28px;
font-weight: 700;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.login-subtitle {
margin: 8px 0 0;
color: #666;
font-size: 14px;
}
.login-form {
margin-top: 24px;
}
.login-form :deep(.ant-form-item) {
margin-bottom: 20px;
}
.login-form :deep(.ant-input-affix-wrapper),
.login-form :deep(.ant-input) {
border-radius: 8px;
}
.code-btn {
padding: 0;
height: auto;
font-size: 14px;
}
.form-footer {
text-align: center;
margin-top: 16px;
color: #666;
font-size: 14px;
}
.register-link {
color: #667eea;
text-decoration: none;
font-weight: 500;
margin-left: 4px;
}
.register-link:hover {
text-decoration: underline;
}
</style>