评论分页

This commit is contained in:
2026-09-07 10:33:41 +08:00
parent 7f5bb974fa
commit caa9436e6a
5 changed files with 151 additions and 51 deletions
+72 -31
View File
@@ -272,6 +272,7 @@ function showPage(pageName) {
loadPages();
break;
case 'comments':
loadCommentPostFilter();
loadComments();
break;
case 'users':
@@ -1050,25 +1051,36 @@ async function loadPages() {
}
}
// 加载评论(postId 为空时加载全部)
async function loadComments(postId = '') {
// 评论列表分页与筛选状态(每页 10 条)
const COMMENTS_PAGE_SIZE = 10;
let commentsCurrentPage = 1;
let commentsCurrentPostId = ''; // 当前按文章筛选的 post_id
let commentsCurrentStatus = ''; // 当前按状态筛选的 status
// 加载评论列表(分页 + 文章/状态筛选)
async function loadComments(page = commentsCurrentPage) {
try {
const url = postId ? `${API_BASE}/comments?post_id=${postId}` : `${API_BASE}/comments`;
const res = await fetch(url, { headers: getHeaders() });
const params = new URLSearchParams();
params.set('page', page);
params.set('page_size', COMMENTS_PAGE_SIZE);
if (commentsCurrentPostId) params.set('post_id', commentsCurrentPostId);
if (commentsCurrentStatus) params.set('status', commentsCurrentStatus);
const res = await fetch(`${API_BASE}/comments?${params.toString()}`, { headers: getHeaders() });
const data = await res.json();
// 加载全部评论时刷新文章筛选下拉框
if (!postId) {
populateCommentPostFilter(data.data || []);
}
const list = data.data || [];
const total = data.total || 0;
const totalPages = Math.max(1, data.total_pages || Math.ceil(total / COMMENTS_PAGE_SIZE));
commentsCurrentPage = Math.min(Math.max(1, data.page || page), totalPages);
const tbody = document.getElementById('comments-list');
tbody.innerHTML = data.data?.map(c => `
tbody.innerHTML = list.map(c => `
<tr>
<td>${c.author}</td>
<td>${c.content.substring(0, 50)}${c.content.length > 50 ? '...' : ''}</td>
<td><a href="/post/${encodeURIComponent(c.post_slug || c.post_id)}" target="_blank">${c.post_title || '文章 #' + c.post_id}</a></td>
<td><span class="status-badge status-${c.status}">${c.status}</span></td>
<td><span class="status-badge status-${c.status}">${getStatusText(c.status)}</span></td>
<td>${new Date(c.created_at).toLocaleString()}</td>
<td>
${c.status === 'pending' ? `<button class="btn-success" onclick="approveComment(${c.id})">通过</button>` : ''}
@@ -1076,11 +1088,28 @@ async function loadComments(postId = '') {
</td>
</tr>
`).join('') || '<tr><td colspan="6" style="text-align:center">暂无评论</td></tr>';
renderCommentsPagination(total, totalPages);
} catch (err) {
console.error('加载评论失败:', err);
}
}
// 渲染评论列表分页条
function renderCommentsPagination(total, totalPages) {
const box = document.getElementById('comments-pagination');
if (!box) return;
const buttons = [];
buttons.push(`<button ${commentsCurrentPage <= 1 ? 'disabled' : ''} onclick="loadComments(${commentsCurrentPage - 1})">上一页</button>`);
for (let i = 1; i <= totalPages; i++) {
buttons.push(`<button class="${i === commentsCurrentPage ? 'active' : ''}" onclick="loadComments(${i})">${i}</button>`);
}
buttons.push(`<button ${commentsCurrentPage >= totalPages ? 'disabled' : ''} onclick="loadComments(${commentsCurrentPage + 1})">下一页</button>`);
box.innerHTML = buttons.join('') + `<span class="pagination-info">共 ${total} 条,第 ${commentsCurrentPage}/${totalPages} 页</span>`;
}
// 显示分类表单
function showCategoryForm() {
showModal('category', '新建分类');
@@ -1280,7 +1309,9 @@ function getStatusText(status) {
'published': '已发布',
'draft': '草稿',
'private': '私密',
'pending': '待审核'
'pending': '待审核',
'approved': '已通过',
'spam': '垃圾'
};
return map[status] || status;
}
@@ -1322,33 +1353,43 @@ async function loadUsers() {
}
}
// 填充评论筛选下拉框(所有有评论的文章)
function populateCommentPostFilter(comments) {
// 加载评论筛选下拉框(所有有评论的文章,来自后端接口而非当前页)
async function loadCommentPostFilter() {
const select = document.getElementById('comment-post-filter');
if (!select) return;
try {
const res = await fetch(`${API_BASE}/comments/posts`, { headers: getHeaders() });
const data = await res.json();
// 按文章去重
const posts = new Map();
comments.forEach(c => {
if (!posts.has(c.post_id)) {
posts.set(c.post_id, c.post_title || ('文章 #' + c.post_id));
select.innerHTML = '<option value="">全部文章</option>';
(data.data || []).forEach(p => {
const opt = document.createElement('option');
opt.value = p.id;
opt.textContent = p.title;
opt.title = p.title; // 悬停显示完整标题
select.appendChild(opt);
});
// 恢复当前选中的文章;若已不存在则重置为全部
select.value = commentsCurrentPostId;
if (select.value !== commentsCurrentPostId) {
commentsCurrentPostId = '';
select.value = '';
}
});
select.innerHTML = '<option value="">全部文章</option>';
posts.forEach((title, id) => {
const opt = document.createElement('option');
opt.value = id;
opt.textContent = title;
opt.title = title; // 悬停显示完整标题
select.appendChild(opt);
});
select.value = '';
} catch (err) {
console.error('加载文章筛选失败:', err);
}
}
// 按选中文章过滤评论列表
function filterCommentsByPost() {
loadComments(document.getElementById('comment-post-filter').value);
commentsCurrentPostId = document.getElementById('comment-post-filter').value;
loadComments(1);
}
// 按选中状态过滤评论列表
function filterCommentsByStatus() {
commentsCurrentStatus = document.getElementById('comment-status-filter').value;
loadComments(1);
}
// 加载基础设置