leeBlog / app /templates /admin /dashboard.html
mistpe's picture
Update app/templates/admin/dashboard.html
406a65a verified
{% extends "base.html" %}
{% block title %}管理面板 - Wisdom Hub{% endblock %}
{% block content %}
<div class="dashboard-container" style="
max-width: 1200px;
margin: 0 auto;
background: linear-gradient(135deg, rgba(255, 255, 255, 0.9), rgba(255, 255, 255, 0.8));
backdrop-filter: blur(10px);
border-radius: 24px;
box-shadow: 0 8px 32px rgba(99, 145, 197, 0.15);
border: 1px solid rgba(99, 145, 197, 0.2);
padding: 2rem;
">
<div class="dashboard-header" style="
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 2rem;
padding-bottom: 1.5rem;
border-bottom: 2px solid #B3CFEF;
">
<div style="display: flex; align-items: center; gap: 1rem;">
<i class="fas fa-chart-line" style="
font-size: 2rem;
color: #6391C5;
"></i>
<h2 style="
font-size: 1.75rem;
font-weight: 600;
color: #6391C5;
margin: 0;
">文章管理</h2>
</div>
<div class="dashboard-actions" style="
display: flex;
gap: 1rem;
">
<button onclick="location.href='{{ url_for('admin.editor') }}'" style="
padding: 0.75rem 1.5rem;
background: linear-gradient(135deg, #6391C5, #C5CDFD);
color: white;
border: none;
border-radius: 12px;
font-weight: 500;
cursor: pointer;
transition: all 0.3s ease;
display: flex;
align-items: center;
gap: 0.5rem;
">
<i class="fas fa-plus"></i>
新建文章
</button>
<button onclick="exportData()" style="
padding: 0.75rem 1.5rem;
background: rgba(99, 145, 197, 0.1);
color: #6391C5;
border: 2px solid #B3CFEF;
border-radius: 12px;
font-weight: 500;
cursor: pointer;
transition: all 0.3s ease;
display: flex;
align-items: center;
gap: 0.5rem;
">
<i class="fas fa-download"></i>
导出数据
</button>
<button onclick="document.getElementById('importInput').click()" style="
padding: 0.75rem 1.5rem;
background: rgba(99, 145, 197, 0.1);
color: #6391C5;
border: 2px solid #B3CFEF;
border-radius: 12px;
font-weight: 500;
cursor: pointer;
transition: all 0.3s ease;
display: flex;
align-items: center;
gap: 0.5rem;
">
<i class="fas fa-upload"></i>
导入数据
</button>
<input type="file" id="importInput" style="display: none" accept=".db">
</div>
</div>
<div class="articles-table" style="
background: white;
border-radius: 16px;
box-shadow: 0 4px 16px rgba(99, 145, 197, 0.1);
overflow: hidden;
">
<table style="width: 100%; border-collapse: collapse;">
<thead>
<tr style="background: #FEEEDA;">
<th style="
text-align: left;
padding: 1rem 1.5rem;
color: #6391C5;
font-weight: 600;
border-bottom: 2px solid #B3CFEF;
">标题</th>
<th style="
text-align: left;
padding: 1rem 1.5rem;
color: #6391C5;
font-weight: 600;
border-bottom: 2px solid #B3CFEF;
">创建时间</th>
<th style="
text-align: left;
padding: 1rem 1.5rem;
color: #6391C5;
font-weight: 600;
border-bottom: 2px solid #B3CFEF;
">更新时间</th>
<th style="
text-align: left;
padding: 1rem 1.5rem;
color: #6391C5;
font-weight: 600;
border-bottom: 2px solid #B3CFEF;
">操作</th>
</tr>
</thead>
<tbody>
{% for article in articles %}
<tr style="transition: all 0.3s ease;">
<td style="
padding: 1rem 1.5rem;
border-bottom: 1px solid #B3CFEF;
color: #6391C5;
">{{ article.title }}</td>
<td style="
padding: 1rem 1.5rem;
border-bottom: 1px solid #B3CFEF;
color: #6391C5;
">{{ article.created_at.strftime('%Y-%m-%d') }}</td>
<td style="
padding: 1rem 1.5rem;
border-bottom: 1px solid #B3CFEF;
color: #6391C5;
">{{ article.updated_at.strftime('%Y-%m-%d') }}</td>
<td style="
padding: 1rem 1.5rem;
border-bottom: 1px solid #B3CFEF;
">
<div style="display: flex; gap: 0.5rem;">
<a href="{{ url_for('admin.editor', slug=article.slug) }}" style="
padding: 0.5rem 1rem;
background: linear-gradient(135deg, #6391C5, #C5CDFD);
color: white;
border-radius: 8px;
text-decoration: none;
font-size: 0.875rem;
transition: all 0.3s ease;
">编辑</a>
<button onclick="deleteArticle('{{ article.slug }}')" style="
padding: 0.5rem 1rem;
background: rgba(255, 71, 87, 0.1);
color: #ff4757;
border: 1px solid rgba(255, 71, 87, 0.2);
border-radius: 8px;
font-size: 0.875rem;
cursor: pointer;
transition: all 0.3s ease;
">删除</button>
</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
<script>
// 表格行悬停效果
document.querySelectorAll('tbody tr').forEach(row => {
row.addEventListener('mouseenter', () => {
row.style.background = 'rgba(99, 145, 197, 0.05)';
});
row.addEventListener('mouseleave', () => {
row.style.background = 'white';
});
});
// 按钮悬停效果
document.querySelectorAll('button').forEach(button => {
button.addEventListener('mouseenter', () => {
if (button.style.background.includes('linear-gradient')) {
button.style.transform = 'translateY(-2px)';
button.style.boxShadow = '0 4px 12px rgba(99, 145, 197, 0.2)';
} else if (button.style.background.includes('rgba(255, 71, 87')) {
button.style.background = 'rgba(255, 71, 87, 0.2)';
} else {
button.style.borderColor = '#6391C5';
button.style.background = 'rgba(99, 145, 197, 0.15)';
}
});
button.addEventListener('mouseleave', () => {
if (button.style.background.includes('linear-gradient')) {
button.style.transform = 'none';
button.style.boxShadow = 'none';
} else if (button.style.background.includes('rgba(255, 71, 87')) {
button.style.background = 'rgba(255, 71, 87, 0.1)';
} else {
button.style.borderColor = '#B3CFEF';
button.style.background = 'rgba(99, 145, 197, 0.1)';
}
});
});
// 编辑链接悬停效果
document.querySelectorAll('a').forEach(link => {
if (link.style.background.includes('linear-gradient')) {
link.addEventListener('mouseenter', () => {
link.style.transform = 'translateY(-2px)';
link.style.boxShadow = '0 4px 12px rgba(99, 145, 197, 0.2)';
});
link.addEventListener('mouseleave', () => {
link.style.transform = 'none';
link.style.boxShadow = 'none';
});
}
});
async function deleteArticle(slug) {
if (!confirm('确定要删除这篇文章吗?')) return;
try {
const response = await fetch(`/api/articles/${slug}`, {
method: 'DELETE'
});
if (response.ok) {
location.reload();
}
} catch (error) {
console.error('Error:', error);
alert('删除失败,请重试');
}
}
async function exportData() {
try {
window.location.href = '/api/export';
} catch (error) {
console.error('Error:', error);
alert('导出失败,请重试');
}
}
document.getElementById('importInput').addEventListener('change', async (event) => {
const file = event.target.files[0];
if (!file) return;
try {
const formData = new FormData();
formData.append('file', file);
const response = await fetch('/api/import', {
method: 'POST',
body: formData
});
const data = await response.json();
if (response.ok) {
alert('导入成功,页面将刷新');
location.reload();
} else {
throw new Error(data.error || '导入失败');
}
} catch (error) {
console.error('Error:', error);
alert('导入失败:' + error.message);
}
});
</script>
{% endblock %}