|
|
<!DOCTYPE html> |
|
|
<html lang="zh"> |
|
|
<head> |
|
|
<meta charset="UTF-8"> |
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
|
<title>{% block title %}个人博客{% endblock %}</title> |
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css"> |
|
|
<style> |
|
|
:root { |
|
|
--primary-blue: #6391C5; |
|
|
--light-blue: #B3CFEF; |
|
|
--warm-cream: #FEEEDA; |
|
|
--soft-purple: #C5CDFD; |
|
|
--text-dark: #2C3E50; |
|
|
--bg-light: #F8FAFC; |
|
|
--sidebar-width: 280px; |
|
|
--header-height: 70px; |
|
|
} |
|
|
|
|
|
* { |
|
|
margin: 0; |
|
|
padding: 0; |
|
|
box-sizing: border-box; |
|
|
} |
|
|
|
|
|
body { |
|
|
font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; |
|
|
line-height: 1.6; |
|
|
color: var(--text-dark); |
|
|
background-color: var(--bg-light); |
|
|
min-height: 100vh; |
|
|
} |
|
|
|
|
|
|
|
|
.app-container { |
|
|
display: flex; |
|
|
min-height: 100vh; |
|
|
} |
|
|
|
|
|
|
|
|
.sidebar { |
|
|
width: var(--sidebar-width); |
|
|
height: 100vh; |
|
|
position: fixed; |
|
|
left: 0; |
|
|
top: 0; |
|
|
background: white; |
|
|
border-right: 2px solid rgba(99, 145, 197, 0.1); |
|
|
display: flex; |
|
|
flex-direction: column; |
|
|
transition: transform 0.3s ease; |
|
|
z-index: 100; |
|
|
} |
|
|
|
|
|
.sidebar-header { |
|
|
padding: 2rem; |
|
|
border-bottom: 2px solid rgba(99, 145, 197, 0.1); |
|
|
} |
|
|
|
|
|
.logo { |
|
|
display: flex; |
|
|
align-items: center; |
|
|
gap: 1rem; |
|
|
text-decoration: none; |
|
|
color: var(--primary-blue); |
|
|
font-size: 1.5rem; |
|
|
font-weight: 600; |
|
|
} |
|
|
|
|
|
.logo i { |
|
|
font-size: 2rem; |
|
|
background: linear-gradient(135deg, var(--primary-blue), var(--light-blue)); |
|
|
-webkit-background-clip: text; |
|
|
-webkit-text-fill-color: transparent; |
|
|
transition: transform 0.3s ease; |
|
|
} |
|
|
|
|
|
.logo:hover i { |
|
|
transform: rotate(-10deg); |
|
|
} |
|
|
|
|
|
.sidebar-content { |
|
|
flex: 1; |
|
|
padding: 2rem 1rem; |
|
|
overflow-y: auto; |
|
|
} |
|
|
|
|
|
.nav-group { |
|
|
margin-bottom: 2rem; |
|
|
} |
|
|
|
|
|
.nav-group-title { |
|
|
font-size: 0.875rem; |
|
|
font-weight: 600; |
|
|
color: #64748B; |
|
|
text-transform: uppercase; |
|
|
letter-spacing: 0.05em; |
|
|
padding: 0 1rem; |
|
|
margin-bottom: 1rem; |
|
|
} |
|
|
|
|
|
.nav-links { |
|
|
display: flex; |
|
|
flex-direction: column; |
|
|
gap: 0.5rem; |
|
|
} |
|
|
|
|
|
.nav-link { |
|
|
display: flex; |
|
|
align-items: center; |
|
|
gap: 1rem; |
|
|
padding: 0.875rem 1rem; |
|
|
color: var(--text-dark); |
|
|
text-decoration: none; |
|
|
border-radius: 12px; |
|
|
transition: all 0.3s ease; |
|
|
font-weight: 500; |
|
|
position: relative; |
|
|
overflow: hidden; |
|
|
} |
|
|
|
|
|
.nav-link::before { |
|
|
content: ''; |
|
|
position: absolute; |
|
|
left: 0; |
|
|
top: 0; |
|
|
width: 4px; |
|
|
height: 100%; |
|
|
background: linear-gradient(135deg, var(--primary-blue), var(--light-blue)); |
|
|
opacity: 0; |
|
|
transition: opacity 0.3s ease; |
|
|
} |
|
|
|
|
|
.nav-link:hover { |
|
|
background: linear-gradient(to right, rgba(99, 145, 197, 0.1), transparent); |
|
|
} |
|
|
|
|
|
.nav-link:hover::before { |
|
|
opacity: 1; |
|
|
} |
|
|
|
|
|
.nav-link i { |
|
|
font-size: 1.25rem; |
|
|
color: var(--primary-blue); |
|
|
transition: transform 0.3s ease; |
|
|
} |
|
|
|
|
|
.nav-link:hover i { |
|
|
transform: translateX(4px); |
|
|
} |
|
|
|
|
|
.nav-link span { |
|
|
font-size: 1.0625rem; |
|
|
} |
|
|
|
|
|
.sidebar-footer { |
|
|
padding: 1.5rem; |
|
|
border-top: 2px solid rgba(99, 145, 197, 0.1); |
|
|
display: flex; |
|
|
align-items: center; |
|
|
gap: 1rem; |
|
|
} |
|
|
|
|
|
|
|
|
.top-header { |
|
|
display: none; |
|
|
position: fixed; |
|
|
top: 0; |
|
|
left: 0; |
|
|
right: 0; |
|
|
height: var(--header-height); |
|
|
background: white; |
|
|
border-bottom: 2px solid rgba(99, 145, 197, 0.1); |
|
|
padding: 0 1.5rem; |
|
|
z-index: 99; |
|
|
} |
|
|
|
|
|
.header-content { |
|
|
height: 100%; |
|
|
display: flex; |
|
|
align-items: center; |
|
|
justify-content: space-between; |
|
|
} |
|
|
|
|
|
.header-nav { |
|
|
display: flex; |
|
|
align-items: center; |
|
|
gap: 1.5rem; |
|
|
} |
|
|
|
|
|
.menu-toggle { |
|
|
display: none; |
|
|
background: none; |
|
|
border: none; |
|
|
color: var(--primary-blue); |
|
|
font-size: 1.5rem; |
|
|
cursor: pointer; |
|
|
padding: 0.5rem; |
|
|
border-radius: 8px; |
|
|
transition: all 0.3s ease; |
|
|
} |
|
|
|
|
|
.menu-toggle:hover { |
|
|
background: rgba(99, 145, 197, 0.1); |
|
|
} |
|
|
|
|
|
|
|
|
.main-content { |
|
|
flex: 1; |
|
|
margin-left: var(--sidebar-width); |
|
|
padding: 2rem; |
|
|
position: relative; |
|
|
min-height: 100vh; |
|
|
} |
|
|
|
|
|
|
|
|
@media (max-width: 768px) { |
|
|
.sidebar { |
|
|
transform: translateX(-100%); |
|
|
} |
|
|
|
|
|
.sidebar.active { |
|
|
transform: translateX(0); |
|
|
} |
|
|
|
|
|
.top-header { |
|
|
display: block; |
|
|
} |
|
|
|
|
|
.menu-toggle { |
|
|
display: block; |
|
|
} |
|
|
|
|
|
.main-content { |
|
|
margin-left: 0; |
|
|
margin-top: var(--header-height); |
|
|
padding: 1.5rem; |
|
|
max-width: 100vh; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
.overlay { |
|
|
display: none; |
|
|
position: fixed; |
|
|
top: 0; |
|
|
left: 0; |
|
|
right: 0; |
|
|
bottom: 0; |
|
|
background: rgba(0, 0, 0, 0.5); |
|
|
backdrop-filter: blur(4px); |
|
|
z-index: 98; |
|
|
opacity: 0; |
|
|
transition: opacity 0.3s ease; |
|
|
} |
|
|
|
|
|
.overlay.active { |
|
|
display: block; |
|
|
opacity: 1; |
|
|
} |
|
|
|
|
|
|
|
|
::-webkit-scrollbar { |
|
|
width: 8px; |
|
|
} |
|
|
|
|
|
::-webkit-scrollbar-track { |
|
|
background: transparent; |
|
|
} |
|
|
|
|
|
::-webkit-scrollbar-thumb { |
|
|
background: var(--light-blue); |
|
|
border-radius: 4px; |
|
|
} |
|
|
|
|
|
::-webkit-scrollbar-thumb:hover { |
|
|
background: var(--primary-blue); |
|
|
} |
|
|
</style> |
|
|
{% block extra_css %}{% endblock %} |
|
|
</head> |
|
|
<body> |
|
|
<div class="app-container"> |
|
|
|
|
|
<header class="top-header"> |
|
|
<div class="header-content"> |
|
|
<button class="menu-toggle" id="menuToggle"> |
|
|
<i class="fas fa-bars"></i> |
|
|
</button> |
|
|
<a href="{{ url_for('main.index') }}" class="logo"> |
|
|
<i class="fas fa-feather"></i> |
|
|
<span>博客</span> |
|
|
</a> |
|
|
<nav class="header-nav"> |
|
|
<a href="{{ url_for('main.index') }}" class="nav-link"> |
|
|
<i class="fas fa-home"></i> |
|
|
<span>首页</span> |
|
|
</a> |
|
|
{% if session.get('logged_in') %} |
|
|
<a href="{{ url_for('admin.dashboard') }}" class="nav-link"> |
|
|
<i class="fas fa-cog"></i> |
|
|
<span>管理</span> |
|
|
</a> |
|
|
{% endif %} |
|
|
</nav> |
|
|
</div> |
|
|
</header> |
|
|
|
|
|
|
|
|
<div class="overlay" id="overlay"></div> |
|
|
|
|
|
|
|
|
<aside class="sidebar" id="sidebar"> |
|
|
<div class="sidebar-header"> |
|
|
<a href="{{ url_for('main.index') }}" class="logo"> |
|
|
<i class="fas fa-feather"></i> |
|
|
<span>Wisdom Hub</span> |
|
|
</a> |
|
|
</div> |
|
|
|
|
|
<div class="sidebar-content"> |
|
|
<nav class="nav-group"> |
|
|
<h3 class="nav-group-title">导航</h3> |
|
|
<div class="nav-links"> |
|
|
<a href="{{ url_for('main.index') }}" class="nav-link"> |
|
|
<i class="fas fa-home"></i> |
|
|
<span>首页</span> |
|
|
</a> |
|
|
{% if session.get('logged_in') %} |
|
|
<a href="{{ url_for('admin.dashboard') }}" class="nav-link"> |
|
|
<i class="fas fa-cog"></i> |
|
|
<span>管理中心</span> |
|
|
</a> |
|
|
{% endif %} |
|
|
</div> |
|
|
</nav> |
|
|
|
|
|
{% if session.get('logged_in') %} |
|
|
<nav class="nav-group"> |
|
|
<h3 class="nav-group-title">内容管理</h3> |
|
|
<div class="nav-links"> |
|
|
<a href="{{ url_for('admin.editor') }}" class="nav-link"> |
|
|
<i class="fas fa-edit"></i> |
|
|
<span>写文章</span> |
|
|
</a> |
|
|
</div> |
|
|
</nav> |
|
|
{% endif %} |
|
|
</div> |
|
|
|
|
|
<div class="sidebar-footer"> |
|
|
{% if session.get('logged_in') %} |
|
|
<form action="{{ url_for('admin.login') }}" method="POST" style="width: 100%;"> |
|
|
<button type="submit" class="nav-link" style="width: 100%; text-align: left; background: none; border: none; cursor: pointer;"> |
|
|
<i class="fas fa-sign-out-alt"></i> |
|
|
<span>退出登录</span> |
|
|
</button> |
|
|
</form> |
|
|
{% else %} |
|
|
<a href="{{ url_for('admin.login') }}" class="nav-link"> |
|
|
<i class="fas fa-sign-in-alt"></i> |
|
|
<span>登录</span> |
|
|
</a> |
|
|
{% endif %} |
|
|
</div> |
|
|
</aside> |
|
|
|
|
|
|
|
|
<main class="main-content"> |
|
|
{% block content %}{% endblock %} |
|
|
</main> |
|
|
</div> |
|
|
|
|
|
<script> |
|
|
|
|
|
const menuToggle = document.getElementById('menuToggle'); |
|
|
const sidebar = document.getElementById('sidebar'); |
|
|
const overlay = document.getElementById('overlay'); |
|
|
|
|
|
function toggleMenu() { |
|
|
sidebar.classList.toggle('active'); |
|
|
overlay.classList.toggle('active'); |
|
|
document.body.style.overflow = sidebar.classList.contains('active') ? 'hidden' : ''; |
|
|
} |
|
|
|
|
|
menuToggle.addEventListener('click', toggleMenu); |
|
|
overlay.addEventListener('click', toggleMenu); |
|
|
|
|
|
|
|
|
window.addEventListener('resize', () => { |
|
|
if (window.innerWidth > 768 && sidebar.classList.contains('active')) { |
|
|
sidebar.classList.remove('active'); |
|
|
overlay.classList.remove('active'); |
|
|
document.body.style.overflow = ''; |
|
|
} |
|
|
}); |
|
|
</script> |
|
|
|
|
|
{% block extra_js %}{% endblock %} |
|
|
</body> |
|
|
</html> |