201 lines
7.9 KiB
HTML
201 lines
7.9 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>{% block title %}钢琴练习方案管理系统{% endblock %}</title>
|
|
|
|
<!-- 公共CSS -->
|
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.0/font/bootstrap-icons.css" rel="stylesheet">
|
|
{% block extra_css %}{% endblock %}
|
|
|
|
<style>
|
|
body { background-color: #f5f7fa; }
|
|
.sidebar { min-height: 100vh; background: #2c3e50; color: white; }
|
|
.sidebar .nav-link { color: rgba(255,255,255,0.8); padding: 12px 20px; }
|
|
.sidebar .nav-link:hover, .sidebar .nav-link.active { background: rgba(255,255,255,0.1); color: white; }
|
|
.main-content { padding: 20px; }
|
|
.card { border: none; border-radius: 10px; box-shadow: 0 2px 10px rgba(0,0,0,0.05); }
|
|
|
|
/* 移动端响应式 */
|
|
@media (max-width: 767.98px) {
|
|
.sidebar {
|
|
position: fixed;
|
|
top: 60px;
|
|
left: 0;
|
|
width: 100%;
|
|
min-height: auto;
|
|
max-height: calc(100vh - 60px);
|
|
z-index: 1040;
|
|
overflow-y: auto;
|
|
transform: translateY(-100%);
|
|
transition: transform 0.3s ease;
|
|
}
|
|
.sidebar.collapsed {
|
|
transform: translateY(-100%);
|
|
}
|
|
.sidebar:not(.collapsed) {
|
|
transform: translateY(0);
|
|
}
|
|
.main-content {
|
|
margin-top: 60px;
|
|
padding: 10px;
|
|
}
|
|
.mobile-nav-toggle {
|
|
display: flex !important;
|
|
}
|
|
}
|
|
@media (min-width: 768px) {
|
|
.mobile-nav-toggle {
|
|
display: none !important;
|
|
}
|
|
.sidebar {
|
|
position: static;
|
|
transform: none !important;
|
|
}
|
|
.sidebar.collapsed {
|
|
transform: none !important;
|
|
}
|
|
}
|
|
</style>
|
|
{% block page_css %}{% endblock %}
|
|
</head>
|
|
<body>
|
|
<!-- 移动端顶部导航 -->
|
|
<nav class="mobile-nav-toggle navbar navbar-dark bg-dark d-flex d-md-none" style="position:fixed;top:0;left:0;right:0;z-index:1050;padding:10px;">
|
|
<div class="container-fluid d-flex justify-content-between align-items-center">
|
|
<div>
|
|
<span class="navbar-brand mb-0"><i class="bi bi-music-note-beamed"></i> 钢琴方案</span>
|
|
<small id="mobileUserDisplay" class="d-block text-white-50" style="font-size:10px;"></small>
|
|
</div>
|
|
<button class="btn btn-outline-light btn-sm" onclick="toggleMobileNav()">
|
|
<i class="bi bi-list"></i>
|
|
</button>
|
|
</div>
|
|
</nav>
|
|
|
|
<div class="container-fluid">
|
|
<div class="row">
|
|
<!-- 侧边栏 -->
|
|
<div class="col-md-2 sidebar p-0 collapsed" id="sidebar">
|
|
<div class="p-3 text-center border-bottom border-secondary d-none d-md-block">
|
|
<h5><i class="bi bi-music-note-beamed"></i> 钢琴方案</h5>
|
|
<small id="currentUserDisplay" class="text-light"></small>
|
|
</div>
|
|
<nav class="nav flex-column">
|
|
{% block sidebar_nav %}{% endblock %}
|
|
</nav>
|
|
</div>
|
|
|
|
<!-- 主内容区 -->
|
|
<div class="col-md-10 main-content">
|
|
{% block content %}{% endblock %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 公共JS -->
|
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
|
<script>
|
|
// 移动端导航切换
|
|
function toggleMobileNav() {
|
|
const sidebar = document.getElementById('sidebar');
|
|
if (sidebar) {
|
|
sidebar.classList.toggle('collapsed');
|
|
}
|
|
}
|
|
|
|
// 点击导航链接后关闭移动端导航
|
|
document.querySelectorAll('.sidebar .nav-link').forEach(link => {
|
|
link.addEventListener('click', () => {
|
|
if (window.innerWidth < 768) {
|
|
toggleMobileNav();
|
|
}
|
|
});
|
|
});
|
|
|
|
// 退出登录
|
|
function logout() {
|
|
if (!confirm('确定要退出登录吗?')) return;
|
|
fetch('/api/logout', { method: 'POST' }).then(() => window.location.href = '/login');
|
|
}
|
|
|
|
// 修改密码
|
|
function showChangePasswordModal() {
|
|
document.getElementById('oldPassword').value = '';
|
|
document.getElementById('newPassword').value = '';
|
|
document.getElementById('confirmPassword').value = '';
|
|
new bootstrap.Modal(document.getElementById('changePwdModal')).show();
|
|
}
|
|
</script>
|
|
{% block extra_js %}{% endblock %}
|
|
|
|
<!-- 修改密码弹窗 -->
|
|
<div class="modal fade" id="changePwdModal" tabindex="-1">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title">修改密码</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<form id="changePwdForm">
|
|
<div class="mb-3">
|
|
<label class="form-label">原密码</label>
|
|
<input type="password" class="form-control" id="oldPassword" required>
|
|
</div>
|
|
<div class="mb-3">
|
|
<label class="form-label">新密码</label>
|
|
<input type="password" class="form-control" id="newPassword" required>
|
|
<div class="form-text">8位以上,包含大小写字母、数字和特殊字符</div>
|
|
</div>
|
|
<div class="mb-3">
|
|
<label class="form-label">确认新密码</label>
|
|
<input type="password" class="form-control" id="confirmPassword" required>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
|
|
<button type="button" class="btn btn-primary" id="changePwdBtn">确认修改</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
document.getElementById('changePwdBtn').addEventListener('click', function() {
|
|
const oldPassword = document.getElementById('oldPassword').value;
|
|
const newPassword = document.getElementById('newPassword').value;
|
|
const confirmPassword = document.getElementById('confirmPassword').value;
|
|
|
|
if (!oldPassword || !newPassword || !confirmPassword) {
|
|
alert('请填写完整');
|
|
return;
|
|
}
|
|
if (newPassword !== confirmPassword) {
|
|
alert('两次输入的新密码不一致');
|
|
return;
|
|
}
|
|
|
|
fetch('/api/users/change-password', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ old_password: oldPassword, new_password: newPassword })
|
|
}).then(r => r.json()).then(data => {
|
|
if (data.error) {
|
|
alert(data.error);
|
|
} else {
|
|
alert('密码修改成功,请重新登录');
|
|
logout();
|
|
}
|
|
}).catch(err => {
|
|
console.error(err);
|
|
alert('请求失败');
|
|
});
|
|
});
|
|
</script>
|
|
</body>
|
|
</html>
|