CHM_attendance/app/templates/auth/change_password.html
superlishunqin e7fa4bc030 first commit
2025-06-11 19:56:34 +08:00

238 lines
9.4 KiB
HTML
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.

{% extends "layout/base.html" %}
{% block title %}修改密码 - CHM考勤管理系统{% endblock %}
{% block content %}
<div class="container-fluid py-4">
<div class="row">
<div class="col-12">
<!-- 页面标题 -->
<div class="d-flex justify-content-between align-items-center mb-4">
<h2><i class="fas fa-key me-2"></i>修改密码</h2>
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a href="{{ url_for('admin.dashboard' if current_user.is_admin() else 'student.dashboard') }}">
{% if current_user.is_admin() %}控制台{% else %}首页{% endif %}
</a>
</li>
<li class="breadcrumb-item"><a href="{{ url_for('auth.profile') }}">个人信息</a></li>
<li class="breadcrumb-item active">修改密码</li>
</ol>
</nav>
</div>
<!-- 修改密码表单 -->
<div class="row">
<div class="col-lg-6 mx-auto">
<div class="card shadow">
<div class="card-header bg-warning text-dark">
<h5 class="mb-0">
<i class="fas fa-shield-alt me-2"></i>安全设置
</h5>
</div>
<div class="card-body">
<!-- 安全提示 -->
<div class="alert alert-info">
<i class="fas fa-info-circle me-2"></i>
<strong>密码要求:</strong>
<ul class="mb-0 mt-2">
<li>长度至少6位</li>
<li>必须包含字母和数字</li>
<li>建议使用字母、数字和特殊字符的组合</li>
</ul>
</div>
<form method="POST" id="changePasswordForm">
<!-- 当前密码 -->
<div class="mb-3">
<label for="current_password" class="form-label">
<i class="fas fa-lock me-1"></i>当前密码 <span class="text-danger">*</span>
</label>
<div class="input-group">
<input type="password" class="form-control" id="current_password" name="current_password" required>
<button class="btn btn-outline-secondary" type="button" onclick="togglePassword('current_password')">
<i class="fas fa-eye"></i>
</button>
</div>
</div>
<!-- 新密码 -->
<div class="mb-3">
<label for="new_password" class="form-label">
<i class="fas fa-key me-1"></i>新密码 <span class="text-danger">*</span>
</label>
<div class="input-group">
<input type="password" class="form-control" id="new_password" name="new_password" required>
<button class="btn btn-outline-secondary" type="button" onclick="togglePassword('new_password')">
<i class="fas fa-eye"></i>
</button>
</div>
<div class="form-text">
<div id="password-strength" class="mt-2"></div>
</div>
</div>
<!-- 确认密码 -->
<div class="mb-4">
<label for="confirm_password" class="form-label">
<i class="fas fa-check-double me-1"></i>确认新密码 <span class="text-danger">*</span>
</label>
<div class="input-group">
<input type="password" class="form-control" id="confirm_password" name="confirm_password" required>
<button class="btn btn-outline-secondary" type="button" onclick="togglePassword('confirm_password')">
<i class="fas fa-eye"></i>
</button>
</div>
<div id="password-match" class="form-text"></div>
</div>
<!-- 操作按钮 -->
<div class="d-grid gap-2 d-md-flex justify-content-md-center">
<button type="submit" class="btn btn-primary btn-lg me-md-2">
<i class="fas fa-save me-1"></i>保存密码
</button>
<a href="{{ url_for('auth.profile') }}" class="btn btn-secondary btn-lg">
<i class="fas fa-times me-1"></i>取消
</a>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block extra_css %}
<style>
.card {
border: none;
border-radius: 10px;
}
.card-header {
border-radius: 10px 10px 0 0 !important;
}
.input-group .btn {
border-left: none;
}
.password-strength-weak { color: #dc3545; }
.password-strength-medium { color: #ffc107; }
.password-strength-strong { color: #28a745; }
</style>
{% endblock %}
{% block extra_js %}
<script>
// 切换密码显示/隐藏
function togglePassword(fieldId) {
const field = document.getElementById(fieldId);
const button = field.nextElementSibling;
const icon = button.querySelector('i');
if (field.type === 'password') {
field.type = 'text';
icon.className = 'fas fa-eye-slash';
} else {
field.type = 'password';
icon.className = 'fas fa-eye';
}
}
// 密码强度检查
document.getElementById('new_password').addEventListener('input', function() {
const password = this.value;
const strengthDiv = document.getElementById('password-strength');
if (password.length === 0) {
strengthDiv.innerHTML = '';
return;
}
let score = 0;
let feedback = [];
// 长度检查
if (password.length >= 6) score += 1;
else feedback.push('至少6位字符');
// 包含字母
if (/[a-zA-Z]/.test(password)) score += 1;
else feedback.push('包含字母');
// 包含数字
if (/\d/.test(password)) score += 1;
else feedback.push('包含数字');
// 包含特殊字符
if (/[!@#$%^&*(),.?":{}|<>]/.test(password)) score += 1;
let strengthText = '';
let strengthClass = '';
if (score < 2) {
strengthText = '弱';
strengthClass = 'password-strength-weak';
} else if (score < 3) {
strengthText = '中等';
strengthClass = 'password-strength-medium';
} else {
strengthText = '强';
strengthClass = 'password-strength-strong';
}
strengthDiv.innerHTML = `<span class="${strengthClass}">密码强度: ${strengthText}</span>`;
if (feedback.length > 0) {
strengthDiv.innerHTML += `<br><small class="text-muted">建议: ${feedback.join(', ')}</small>`;
}
});
// 密码匹配检查
document.getElementById('confirm_password').addEventListener('input', function() {
const newPassword = document.getElementById('new_password').value;
const confirmPassword = this.value;
const matchDiv = document.getElementById('password-match');
if (confirmPassword.length === 0) {
matchDiv.innerHTML = '';
return;
}
if (newPassword === confirmPassword) {
matchDiv.innerHTML = '<span class="text-success"><i class="fas fa-check me-1"></i>密码匹配</span>';
} else {
matchDiv.innerHTML = '<span class="text-danger"><i class="fas fa-times me-1"></i>密码不匹配</span>';
}
});
// 表单提交验证
document.getElementById('changePasswordForm').addEventListener('submit', function(e) {
const newPassword = document.getElementById('new_password').value;
const confirmPassword = document.getElementById('confirm_password').value;
if (newPassword !== confirmPassword) {
e.preventDefault();
alert('新密码与确认密码不匹配!');
return false;
}
if (newPassword.length < 6) {
e.preventDefault();
alert('新密码长度至少6位');
return false;
}
if (!/^(?=.*[a-zA-Z])(?=.*\d).+$/.test(newPassword)) {
e.preventDefault();
alert('新密码必须包含字母和数字!');
return false;
}
});
</script>
{% endblock %}