392 lines
13 KiB
HTML
392 lines
13 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
||
<title>忘记密码 - OA系统</title>
|
||
<style>
|
||
* {
|
||
margin: 0;
|
||
padding: 0;
|
||
box-sizing: border-box;
|
||
}
|
||
body {
|
||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
min-height: 100vh;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding: 20px;
|
||
}
|
||
.forgot-container {
|
||
background: white;
|
||
border-radius: 12px;
|
||
padding: 32px 24px;
|
||
width: 100%;
|
||
max-width: 400px;
|
||
box-shadow: 0 10px 40px rgba(0,0,0,0.2);
|
||
}
|
||
.logo {
|
||
text-align: center;
|
||
margin-bottom: 32px;
|
||
}
|
||
.logo-icon {
|
||
width: 64px;
|
||
height: 64px;
|
||
background: #1890ff;
|
||
border-radius: 50%;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 32px;
|
||
color: white;
|
||
margin-bottom: 12px;
|
||
}
|
||
.logo-title {
|
||
font-size: 20px;
|
||
font-weight: bold;
|
||
color: #333;
|
||
}
|
||
.step-indicator {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
margin-bottom: 32px;
|
||
padding: 0 10px;
|
||
}
|
||
.step-item {
|
||
flex: 1;
|
||
text-align: center;
|
||
position: relative;
|
||
}
|
||
.step-item::after {
|
||
content: '';
|
||
position: absolute;
|
||
top: 12px;
|
||
left: 50%;
|
||
width: 100%;
|
||
height: 2px;
|
||
background: #e6e6e6;
|
||
z-index: 0;
|
||
}
|
||
.step-item:last-child::after {
|
||
display: none;
|
||
}
|
||
.step-number {
|
||
width: 24px;
|
||
height: 24px;
|
||
border-radius: 50%;
|
||
background: #e6e6e6;
|
||
color: #999;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 12px;
|
||
position: relative;
|
||
z-index: 1;
|
||
}
|
||
.step-item.active .step-number {
|
||
background: #1890ff;
|
||
color: white;
|
||
}
|
||
.step-item.completed .step-number {
|
||
background: #52c41a;
|
||
color: white;
|
||
}
|
||
.step-label {
|
||
font-size: 11px;
|
||
color: #999;
|
||
margin-top: 6px;
|
||
}
|
||
.step-item.active .step-label {
|
||
color: #1890ff;
|
||
}
|
||
.form-item {
|
||
margin-bottom: 20px;
|
||
}
|
||
.form-label {
|
||
display: block;
|
||
margin-bottom: 8px;
|
||
color: #333;
|
||
font-size: 14px;
|
||
font-weight: 500;
|
||
}
|
||
.form-input {
|
||
width: 100%;
|
||
padding: 12px 16px;
|
||
border: 1px solid #e5e5e5;
|
||
border-radius: 8px;
|
||
font-size: 14px;
|
||
}
|
||
.form-input:focus {
|
||
outline: none;
|
||
border-color: #1890ff;
|
||
}
|
||
.method-tabs {
|
||
display: flex;
|
||
gap: 8px;
|
||
margin-bottom: 16px;
|
||
}
|
||
.method-tab {
|
||
flex: 1;
|
||
padding: 10px;
|
||
border: 1px solid #e5e5e5;
|
||
border-radius: 8px;
|
||
background: white;
|
||
color: #666;
|
||
cursor: pointer;
|
||
text-align: center;
|
||
font-size: 13px;
|
||
}
|
||
.method-tab.active {
|
||
background: #1890ff;
|
||
color: white;
|
||
border-color: #1890ff;
|
||
}
|
||
.code-wrapper {
|
||
display: flex;
|
||
gap: 8px;
|
||
}
|
||
.code-input {
|
||
flex: 1;
|
||
}
|
||
.btn-code {
|
||
padding: 12px 20px;
|
||
background: #1890ff;
|
||
color: white;
|
||
border: none;
|
||
border-radius: 8px;
|
||
font-size: 13px;
|
||
white-space: nowrap;
|
||
}
|
||
.btn-code:disabled {
|
||
background: #ccc;
|
||
cursor: not-allowed;
|
||
}
|
||
.btn-submit {
|
||
width: 100%;
|
||
padding: 12px;
|
||
background: #1890ff;
|
||
color: white;
|
||
border: none;
|
||
border-radius: 8px;
|
||
font-size: 16px;
|
||
font-weight: 500;
|
||
cursor: pointer;
|
||
margin-top: 8px;
|
||
}
|
||
.back-login {
|
||
text-align: center;
|
||
margin-top: 24px;
|
||
}
|
||
.back-link {
|
||
color: #1890ff;
|
||
font-size: 14px;
|
||
text-decoration: none;
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="forgot-container">
|
||
<div class="logo">
|
||
<div class="logo-icon">🔒</div>
|
||
<div class="logo-title">找回密码</div>
|
||
</div>
|
||
|
||
<div class="step-indicator">
|
||
<div class="step-item active" id="step1">
|
||
<div class="step-number">1</div>
|
||
<div class="step-label">验证身份</div>
|
||
</div>
|
||
<div class="step-item" id="step2">
|
||
<div class="step-number">2</div>
|
||
<div class="step-label">输入验证码</div>
|
||
</div>
|
||
<div class="step-item" id="step3">
|
||
<div class="step-number">3</div>
|
||
<div class="step-label">设置新密码</div>
|
||
</div>
|
||
</div>
|
||
|
||
<form id="forgotForm">
|
||
<div id="step1-content">
|
||
<div class="form-item">
|
||
<label class="form-label">用户名或手机号/邮箱</label>
|
||
<input type="text" class="form-input" placeholder="请输入用户名、手机号或邮箱" id="username" required>
|
||
</div>
|
||
|
||
<div class="form-item">
|
||
<label class="form-label">找回方式</label>
|
||
<div class="method-tabs">
|
||
<div class="method-tab active" onclick="switchMethod('phone')">手机验证</div>
|
||
<div class="method-tab" onclick="switchMethod('email')">邮箱验证</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="form-item" id="phone-input" style="display: block;">
|
||
<label class="form-label">手机号</label>
|
||
<input type="tel" class="form-input" placeholder="请输入手机号" id="phone">
|
||
</div>
|
||
|
||
<div class="form-item" id="email-input" style="display: none;">
|
||
<label class="form-label">邮箱</label>
|
||
<input type="email" class="form-input" placeholder="请输入邮箱" id="email">
|
||
</div>
|
||
|
||
<button type="button" class="btn-submit" onclick="sendCode()">发送验证码</button>
|
||
</div>
|
||
|
||
<div id="step2-content" style="display: none;">
|
||
<div class="form-item">
|
||
<label class="form-label">验证码</label>
|
||
<div class="code-wrapper">
|
||
<input type="text" class="form-input code-input" placeholder="请输入验证码" id="verifyCode" maxlength="6">
|
||
<button type="button" class="btn-code" id="resendBtn" onclick="sendCode()">重新发送</button>
|
||
</div>
|
||
<div style="font-size: 12px; color: #999; margin-top: 8px;">验证码已发送,请查收</div>
|
||
</div>
|
||
|
||
<button type="button" class="btn-submit" onclick="verifyCode()">验证</button>
|
||
</div>
|
||
|
||
<div id="step3-content" style="display: none;">
|
||
<div class="form-item">
|
||
<label class="form-label">新密码</label>
|
||
<input type="password" class="form-input" placeholder="请输入新密码(8-20位,包含字母和数字)" id="newPassword" required>
|
||
<div style="font-size: 12px; color: #999; margin-top: 4px;">密码长度8-20位,必须包含字母和数字</div>
|
||
</div>
|
||
|
||
<div class="form-item">
|
||
<label class="form-label">确认新密码</label>
|
||
<input type="password" class="form-input" placeholder="请再次输入新密码" id="confirmPassword" required>
|
||
</div>
|
||
|
||
<button type="submit" class="btn-submit">确认重置</button>
|
||
</div>
|
||
</form>
|
||
|
||
<div class="back-login">
|
||
<a href="login.html" class="back-link">← 返回登录</a>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
let currentMethod = 'phone';
|
||
let countdown = 0;
|
||
let countdownTimer = null;
|
||
|
||
function switchMethod(method) {
|
||
currentMethod = method;
|
||
document.querySelectorAll('.method-tab').forEach(tab => tab.classList.remove('active'));
|
||
event.target.classList.add('active');
|
||
|
||
document.getElementById('phone-input').style.display = method === 'phone' ? 'block' : 'none';
|
||
document.getElementById('email-input').style.display = method === 'email' ? 'block' : 'none';
|
||
}
|
||
|
||
function sendCode() {
|
||
const username = document.getElementById('username').value.trim();
|
||
const phone = document.getElementById('phone').value.trim();
|
||
const email = document.getElementById('email').value.trim();
|
||
|
||
if (!username) {
|
||
alert('请输入用户名');
|
||
return;
|
||
}
|
||
|
||
if (currentMethod === 'phone' && !phone) {
|
||
alert('请输入手机号');
|
||
return;
|
||
}
|
||
|
||
if (currentMethod === 'email' && !email) {
|
||
alert('请输入邮箱');
|
||
return;
|
||
}
|
||
|
||
alert('验证码已发送,请查收');
|
||
|
||
document.getElementById('step1-content').style.display = 'none';
|
||
document.getElementById('step2-content').style.display = 'block';
|
||
document.getElementById('step1').classList.remove('active');
|
||
document.getElementById('step1').classList.add('completed');
|
||
document.getElementById('step2').classList.add('active');
|
||
|
||
startCountdown();
|
||
}
|
||
|
||
function startCountdown() {
|
||
countdown = 60;
|
||
const btn = document.getElementById('resendBtn');
|
||
btn.disabled = true;
|
||
|
||
countdownTimer = setInterval(() => {
|
||
countdown--;
|
||
btn.textContent = `重新发送(${countdown}s)`;
|
||
|
||
if (countdown <= 0) {
|
||
clearInterval(countdownTimer);
|
||
btn.disabled = false;
|
||
btn.textContent = '重新发送';
|
||
}
|
||
}, 1000);
|
||
}
|
||
|
||
function verifyCode() {
|
||
const code = document.getElementById('verifyCode').value.trim();
|
||
|
||
if (!code) {
|
||
alert('请输入验证码');
|
||
return;
|
||
}
|
||
|
||
if (code.length !== 6) {
|
||
alert('验证码为6位数字');
|
||
return;
|
||
}
|
||
|
||
alert('验证码验证成功');
|
||
|
||
document.getElementById('step2-content').style.display = 'none';
|
||
document.getElementById('step3-content').style.display = 'block';
|
||
document.getElementById('step2').classList.remove('active');
|
||
document.getElementById('step2').classList.add('completed');
|
||
document.getElementById('step3').classList.add('active');
|
||
}
|
||
|
||
document.getElementById('forgotForm').addEventListener('submit', function(e) {
|
||
e.preventDefault();
|
||
|
||
const newPassword = document.getElementById('newPassword').value;
|
||
const confirmPassword = document.getElementById('confirmPassword').value;
|
||
|
||
if (!newPassword || !confirmPassword) {
|
||
alert('请填写完整信息');
|
||
return;
|
||
}
|
||
|
||
if (newPassword.length < 8 || newPassword.length > 20) {
|
||
alert('密码长度必须在8-20位之间');
|
||
return;
|
||
}
|
||
|
||
if (!/^(?=.*[A-Za-z])(?=.*\d)/.test(newPassword)) {
|
||
alert('密码必须包含字母和数字');
|
||
return;
|
||
}
|
||
|
||
if (newPassword !== confirmPassword) {
|
||
alert('两次输入的新密码不一致');
|
||
return;
|
||
}
|
||
|
||
alert('密码重置成功!请使用新密码登录');
|
||
setTimeout(() => {
|
||
window.location.href = 'login.html';
|
||
}, 1500);
|
||
});
|
||
</script>
|
||
</body>
|
||
</html>
|
||
|