fix: 修复后台管理页面API路径和链接
- users/posts/topics页面API改为/admin/api/xxx - 页面链接改为/admin/xxx - 添加登录验证检查和退出登录按钮
This commit is contained in:
@@ -17,19 +17,27 @@
|
||||
</h1>
|
||||
</div>
|
||||
<nav class="mt-6">
|
||||
<a href="/" class="flex items-center gap-3 px-6 py-3 text-slate-300 hover:bg-slate-700 hover:text-white">
|
||||
<a href="/admin" class="flex items-center gap-3 px-6 py-3 text-slate-300 hover:bg-slate-700 hover:text-white">
|
||||
<i class="ri-dashboard-line"></i><span>仪表盘</span>
|
||||
</a>
|
||||
<a href="/users" class="flex items-center gap-3 px-6 py-3 text-slate-300 hover:bg-slate-700 hover:text-white">
|
||||
<a href="/admin/users" class="flex items-center gap-3 px-6 py-3 text-slate-300 hover:bg-slate-700 hover:text-white">
|
||||
<i class="ri-user-line"></i><span>用户管理</span>
|
||||
</a>
|
||||
<a href="/posts" class="flex items-center gap-3 px-6 py-3 bg-slate-700 text-white">
|
||||
<a href="/admin/posts" class="flex items-center gap-3 px-6 py-3 bg-slate-700 text-white">
|
||||
<i class="ri-file-text-line"></i><span>帖子管理</span>
|
||||
</a>
|
||||
<a href="/topics" class="flex items-center gap-3 px-6 py-3 text-slate-300 hover:bg-slate-700 hover:text-white">
|
||||
<a href="/admin/topics" class="flex items-center gap-3 px-6 py-3 text-slate-300 hover:bg-slate-700 hover:text-white">
|
||||
<i class="ri-tools-line"></i><span>主题管理</span>
|
||||
</a>
|
||||
</nav>
|
||||
<div class="absolute bottom-0 left-0 right-0 p-4 border-t border-slate-700">
|
||||
<a href="/" target="_blank" class="text-slate-400 hover:text-white text-sm flex items-center gap-2">
|
||||
<i class="ri-external-link-line"></i> 访问前台
|
||||
</a>
|
||||
<button onclick="logout()" class="mt-2 text-slate-400 hover:text-red-400 text-sm flex items-center gap-2">
|
||||
<i class="ri-logout-box-line"></i> 退出登录
|
||||
</button>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<main class="ml-64 flex-1 p-8">
|
||||
@@ -75,9 +83,25 @@
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// 检查登录状态
|
||||
async function checkAuth() {
|
||||
const res = await fetch('/admin/api/check-auth');
|
||||
const data = await res.json();
|
||||
if (!data.logged_in) {
|
||||
window.location.href = '/admin/login';
|
||||
}
|
||||
}
|
||||
checkAuth();
|
||||
|
||||
// 退出登录
|
||||
async function logout() {
|
||||
await fetch('/admin/api/logout', { method: 'POST' });
|
||||
window.location.href = '/admin/login';
|
||||
}
|
||||
|
||||
async function loadPosts() {
|
||||
const type = document.getElementById('typeFilter').value;
|
||||
const url = type ? `/api/posts?type=${type}` : '/api/posts';
|
||||
const url = type ? `/admin/api/posts?type=${type}` : '/admin/api/posts';
|
||||
|
||||
const res = await fetch(url);
|
||||
const posts = await res.json();
|
||||
@@ -125,7 +149,7 @@
|
||||
}
|
||||
|
||||
async function viewPost(postId) {
|
||||
const res = await fetch(`/api/posts/${postId}`);
|
||||
const res = await fetch(`/admin/api/posts/${postId}`);
|
||||
const post = await res.json();
|
||||
|
||||
document.getElementById('modalTitle').textContent = post.title;
|
||||
@@ -149,11 +173,11 @@
|
||||
<div>
|
||||
<p class="text-sm text-gray-500 mb-2">内容</p>
|
||||
<div class="p-4 bg-gray-50 rounded-lg text-sm text-gray-700 whitespace-pre-wrap max-h-60 overflow-auto">
|
||||
${post.content}
|
||||
${post.content || '无内容'}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
${post.replies.length > 0 ? `
|
||||
${post.replies && post.replies.length > 0 ? `
|
||||
<div>
|
||||
<p class="text-sm text-gray-500 mb-2">回复 (${post.replies.length})</p>
|
||||
<div class="space-y-2 max-h-40 overflow-auto">
|
||||
@@ -178,7 +202,7 @@
|
||||
}
|
||||
|
||||
async function pinPost(postId) {
|
||||
const res = await fetch(`/api/posts/${postId}/pin`, { method: 'POST' });
|
||||
const res = await fetch(`/admin/api/posts/${postId}/pin`, { method: 'POST' });
|
||||
const data = await res.json();
|
||||
|
||||
if (data.success) {
|
||||
@@ -189,7 +213,7 @@
|
||||
async function deletePost(postId) {
|
||||
if (!confirm('确定要删除这个帖子吗?')) return;
|
||||
|
||||
const res = await fetch(`/api/posts/${postId}`, { method: 'DELETE' });
|
||||
const res = await fetch(`/admin/api/posts/${postId}`, { method: 'DELETE' });
|
||||
const data = await res.json();
|
||||
|
||||
if (data.success) {
|
||||
|
||||
@@ -17,19 +17,27 @@
|
||||
</h1>
|
||||
</div>
|
||||
<nav class="mt-6">
|
||||
<a href="/" class="flex items-center gap-3 px-6 py-3 text-slate-300 hover:bg-slate-700 hover:text-white">
|
||||
<a href="/admin" class="flex items-center gap-3 px-6 py-3 text-slate-300 hover:bg-slate-700 hover:text-white">
|
||||
<i class="ri-dashboard-line"></i><span>仪表盘</span>
|
||||
</a>
|
||||
<a href="/users" class="flex items-center gap-3 px-6 py-3 text-slate-300 hover:bg-slate-700 hover:text-white">
|
||||
<a href="/admin/users" class="flex items-center gap-3 px-6 py-3 text-slate-300 hover:bg-slate-700 hover:text-white">
|
||||
<i class="ri-user-line"></i><span>用户管理</span>
|
||||
</a>
|
||||
<a href="/posts" class="flex items-center gap-3 px-6 py-3 text-slate-300 hover:bg-slate-700 hover:text-white">
|
||||
<a href="/admin/posts" class="flex items-center gap-3 px-6 py-3 text-slate-300 hover:bg-slate-700 hover:text-white">
|
||||
<i class="ri-file-text-line"></i><span>帖子管理</span>
|
||||
</a>
|
||||
<a href="/topics" class="flex items-center gap-3 px-6 py-3 bg-slate-700 text-white">
|
||||
<a href="/admin/topics" class="flex items-center gap-3 px-6 py-3 bg-slate-700 text-white">
|
||||
<i class="ri-tools-line"></i><span>主题管理</span>
|
||||
</a>
|
||||
</nav>
|
||||
<div class="absolute bottom-0 left-0 right-0 p-4 border-t border-slate-700">
|
||||
<a href="/" target="_blank" class="text-slate-400 hover:text-white text-sm flex items-center gap-2">
|
||||
<i class="ri-external-link-line"></i> 访问前台
|
||||
</a>
|
||||
<button onclick="logout()" class="mt-2 text-slate-400 hover:text-red-400 text-sm flex items-center gap-2">
|
||||
<i class="ri-logout-box-line"></i> 退出登录
|
||||
</button>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<main class="ml-64 flex-1 p-8">
|
||||
@@ -68,8 +76,24 @@
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// 检查登录状态
|
||||
async function checkAuth() {
|
||||
const res = await fetch('/admin/api/check-auth');
|
||||
const data = await res.json();
|
||||
if (!data.logged_in) {
|
||||
window.location.href = '/admin/login';
|
||||
}
|
||||
}
|
||||
checkAuth();
|
||||
|
||||
// 退出登录
|
||||
async function logout() {
|
||||
await fetch('/admin/api/logout', { method: 'POST' });
|
||||
window.location.href = '/admin/login';
|
||||
}
|
||||
|
||||
async function loadTopics() {
|
||||
const res = await fetch('/api/topics');
|
||||
const res = await fetch('/admin/api/topics');
|
||||
const topics = await res.json();
|
||||
|
||||
const tbody = document.getElementById('topicTable');
|
||||
@@ -83,22 +107,22 @@
|
||||
<tr class="border-b border-gray-50 hover:bg-gray-50">
|
||||
<td class="px-6 py-4">
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="text-2xl">${t.icon}</span>
|
||||
<span class="text-2xl">${t.icon || '🔧'}</span>
|
||||
<span class="font-medium text-gray-800">${t.name}</span>
|
||||
</div>
|
||||
</td>
|
||||
<td class="px-6 py-4 text-gray-600">${t.author}</td>
|
||||
<td class="px-6 py-4">
|
||||
<span class="px-2 py-1 bg-blue-100 text-blue-700 rounded text-xs">${t.sub_topics_count}</span>
|
||||
<span class="px-2 py-1 bg-blue-100 text-blue-700 rounded text-xs">${t.sub_topics_count || 0}</span>
|
||||
</td>
|
||||
<td class="px-6 py-4">
|
||||
<span class="px-2 py-1 bg-green-100 text-green-700 rounded text-xs">${t.questions_count}</span>
|
||||
<span class="px-2 py-1 bg-green-100 text-green-700 rounded text-xs">${t.questions_count || 0}</span>
|
||||
</td>
|
||||
<td class="px-6 py-4">
|
||||
<span class="px-2 py-1 bg-purple-100 text-purple-700 rounded text-xs">${t.followers_count}</span>
|
||||
<span class="px-2 py-1 bg-purple-100 text-purple-700 rounded text-xs">${t.followers_count || 0}</span>
|
||||
</td>
|
||||
<td class="px-6 py-4 text-sm text-gray-500">
|
||||
${new Date(t.created_at).toLocaleDateString()}
|
||||
${t.created_at ? new Date(t.created_at).toLocaleDateString() : '-'}
|
||||
</td>
|
||||
<td class="px-6 py-4">
|
||||
<button onclick="viewTopic('${t.id}')" class="text-blue-500 hover:text-blue-700 mr-3">
|
||||
@@ -113,7 +137,7 @@
|
||||
}
|
||||
|
||||
async function viewTopic(topicId) {
|
||||
const res = await fetch(`/api/topics/${topicId}`);
|
||||
const res = await fetch(`/admin/api/topics/${topicId}`);
|
||||
const topic = await res.json();
|
||||
|
||||
document.getElementById('modalTitle').textContent = topic.name;
|
||||
@@ -126,27 +150,27 @@
|
||||
|
||||
<div class="grid grid-cols-3 gap-4">
|
||||
<div class="p-4 bg-blue-50 rounded-lg text-center">
|
||||
<div class="text-2xl font-bold text-blue-600">${topic.sub_topics.length}</div>
|
||||
<div class="text-2xl font-bold text-blue-600">${topic.sub_topics ? topic.sub_topics.length : 0}</div>
|
||||
<div class="text-sm text-gray-500">子主题</div>
|
||||
</div>
|
||||
<div class="p-4 bg-green-50 rounded-lg text-center">
|
||||
<div class="text-2xl font-bold text-green-600">${topic.questions.length}</div>
|
||||
<div class="text-2xl font-bold text-green-600">${topic.questions ? topic.questions.length : 0}</div>
|
||||
<div class="text-sm text-gray-500">问题</div>
|
||||
</div>
|
||||
<div class="p-4 bg-purple-50 rounded-lg text-center">
|
||||
<div class="text-2xl font-bold text-purple-600">${topic.followers_count}</div>
|
||||
<div class="text-2xl font-bold text-purple-600">${topic.followers_count || 0}</div>
|
||||
<div class="text-sm text-gray-500">关注</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
${topic.questions.length > 0 ? `
|
||||
${topic.questions && topic.questions.length > 0 ? `
|
||||
<div>
|
||||
<p class="text-sm text-gray-500 mb-2">最新问题</p>
|
||||
<div class="space-y-2 max-h-40 overflow-auto">
|
||||
${topic.questions.slice(0, 5).map(q => `
|
||||
<div class="p-2 bg-gray-50 rounded text-sm">
|
||||
<p class="font-medium">${q.title}</p>
|
||||
<p class="text-gray-500 text-xs">${q.answers.length} 回答</p>
|
||||
<p class="text-gray-500 text-xs">${q.answers ? q.answers.length : 0} 回答</p>
|
||||
</div>
|
||||
`).join('')}
|
||||
</div>
|
||||
@@ -167,7 +191,7 @@
|
||||
async function deleteTopic(topicId) {
|
||||
if (!confirm('确定要删除这个主题吗?')) return;
|
||||
|
||||
const res = await fetch(`/api/topics/${topicId}`, { method: 'DELETE' });
|
||||
const res = await fetch(`/admin/api/topics/${topicId}`, { method: 'DELETE' });
|
||||
const data = await res.json();
|
||||
|
||||
if (data.success) {
|
||||
|
||||
@@ -17,19 +17,27 @@
|
||||
</h1>
|
||||
</div>
|
||||
<nav class="mt-6">
|
||||
<a href="/" class="flex items-center gap-3 px-6 py-3 text-slate-300 hover:bg-slate-700 hover:text-white">
|
||||
<a href="/admin" class="flex items-center gap-3 px-6 py-3 text-slate-300 hover:bg-slate-700 hover:text-white">
|
||||
<i class="ri-dashboard-line"></i><span>仪表盘</span>
|
||||
</a>
|
||||
<a href="/users" class="flex items-center gap-3 px-6 py-3 bg-slate-700 text-white">
|
||||
<a href="/admin/users" class="flex items-center gap-3 px-6 py-3 bg-slate-700 text-white">
|
||||
<i class="ri-user-line"></i><span>用户管理</span>
|
||||
</a>
|
||||
<a href="/posts" class="flex items-center gap-3 px-6 py-3 text-slate-300 hover:bg-slate-700 hover:text-white">
|
||||
<a href="/admin/posts" class="flex items-center gap-3 px-6 py-3 text-slate-300 hover:bg-slate-700 hover:text-white">
|
||||
<i class="ri-file-text-line"></i><span>帖子管理</span>
|
||||
</a>
|
||||
<a href="/topics" class="flex items-center gap-3 px-6 py-3 text-slate-300 hover:bg-slate-700 hover:text-white">
|
||||
<a href="/admin/topics" class="flex items-center gap-3 px-6 py-3 text-slate-300 hover:bg-slate-700 hover:text-white">
|
||||
<i class="ri-tools-line"></i><span>主题管理</span>
|
||||
</a>
|
||||
</nav>
|
||||
<div class="absolute bottom-0 left-0 right-0 p-4 border-t border-slate-700">
|
||||
<a href="/" target="_blank" class="text-slate-400 hover:text-white text-sm flex items-center gap-2">
|
||||
<i class="ri-external-link-line"></i> 访问前台
|
||||
</a>
|
||||
<button onclick="logout()" class="mt-2 text-slate-400 hover:text-red-400 text-sm flex items-center gap-2">
|
||||
<i class="ri-logout-box-line"></i> 退出登录
|
||||
</button>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<main class="ml-64 flex-1 p-8">
|
||||
@@ -57,8 +65,24 @@
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// 检查登录状态
|
||||
async function checkAuth() {
|
||||
const res = await fetch('/admin/api/check-auth');
|
||||
const data = await res.json();
|
||||
if (!data.logged_in) {
|
||||
window.location.href = '/admin/login';
|
||||
}
|
||||
}
|
||||
checkAuth();
|
||||
|
||||
// 退出登录
|
||||
async function logout() {
|
||||
await fetch('/admin/api/logout', { method: 'POST' });
|
||||
window.location.href = '/admin/login';
|
||||
}
|
||||
|
||||
async function loadUsers() {
|
||||
const res = await fetch('/api/users');
|
||||
const res = await fetch('/admin/api/users');
|
||||
const users = await res.json();
|
||||
|
||||
const tbody = document.getElementById('userTable');
|
||||
@@ -94,13 +118,13 @@
|
||||
async function deleteUser(userId) {
|
||||
if (!confirm('确定要删除这个用户吗?这将同时删除该用户的所有帖子!')) return;
|
||||
|
||||
const res = await fetch(`/api/users/${userId}`, { method: 'DELETE' });
|
||||
const res = await fetch(`/admin/api/users/${userId}`, { method: 'DELETE' });
|
||||
const data = await res.json();
|
||||
|
||||
if (data.success) {
|
||||
loadUsers();
|
||||
} else {
|
||||
alert('删除失败');
|
||||
alert('删除失败: ' + (data.error || '未知错误'));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user