feat(admin): 添加评论按域名筛选功能并调整统计页面布局

- 在评论管理页面添加域名筛选功能
- 调整统计页面中卡片顺序,将图表移至概览下方
- 更新文档添加版本更新警告提示
- 修改评论列表API支持域名参数查询
This commit is contained in:
anghunk
2026-01-21 13:37:55 +08:00
parent bbe2bdd820
commit 8fa8748949
5 changed files with 72 additions and 18 deletions

View File

@@ -93,8 +93,13 @@ export function logoutAdmin(): void {
localStorage.removeItem('cwd_admin_token');
}
export function fetchComments(page: number): Promise<CommentListResponse> {
return get<CommentListResponse>(`/admin/comments/list?page=${page}`);
export function fetchComments(page: number, domain?: string): Promise<CommentListResponse> {
const searchParams = new URLSearchParams();
searchParams.set('page', String(page));
if (domain) {
searchParams.set('domain', domain);
}
return get<CommentListResponse>(`/admin/comments/list?${searchParams.toString()}`);
}
export function deleteComment(id: number): Promise<{ message: string }> {

View File

@@ -9,6 +9,12 @@
<option value="pending">待审核</option>
<option value="rejected">已拒绝</option>
</select>
<select v-model="domainFilter" class="toolbar-select">
<option value="">全部域名</option>
<option v-for="item in domainOptions" :key="item" :value="item">
{{ item }}
</option>
</select>
</div>
<div class="toolbar-right">
<button class="toolbar-button" @click="loadComments">刷新</button>
@@ -191,6 +197,7 @@ import {
CommentItem,
CommentListResponse,
fetchComments,
fetchCommentStats,
deleteComment,
updateCommentStatus,
blockIp,
@@ -205,8 +212,11 @@ const pagination = ref<{ page: number; total: number }>({ page: 1, total: 1 });
const loading = ref(false);
const error = ref("");
const statusFilter = ref("");
const domainFilter = ref("");
const jumpPageInput = ref("");
const domainOptions = ref<string[]>([]);
const filteredComments = computed(() => {
if (!statusFilter.value) {
return comments.value;
@@ -263,7 +273,7 @@ async function loadComments(page?: number) {
loading.value = true;
error.value = "";
try {
const res = await fetchComments(targetPage);
const res = await fetchComments(targetPage, domainFilter.value || undefined);
comments.value = res.data;
pagination.value = { page: res.pagination.page, total: res.pagination.total };
} catch (e: any) {
@@ -280,6 +290,11 @@ function updateRoutePage(page: number) {
} else {
query.p = String(page);
}
if (domainFilter.value) {
query.domain = domainFilter.value;
} else {
delete query.domain;
}
router.push({ query });
}
@@ -370,6 +385,20 @@ onMounted(() => {
initialPage = Math.floor(value);
}
}
const d = route.query.domain;
if (typeof d === "string" && d.trim()) {
domainFilter.value = d.trim();
}
fetchCommentStats()
.then((res: CommentListResponse | any) => {
const domains = Array.isArray(res.domains) ? res.domains.map((item: any) => item.domain) : [];
domainOptions.value = Array.from(new Set(domains));
})
.catch(() => {
domainOptions.value = [];
});
loadComments(initialPage);
});
</script>

View File

@@ -9,15 +9,6 @@
{{ toastMessage }}
</div>
<div class="card">
<h3 class="card-title">最近 7 天评论数趋势</h3>
<div v-if="statsLoading" class="page-hint">加载中...</div>
<div v-else-if="statsError" class="page-error">{{ statsError }}</div>
<div v-else class="chart-wrapper">
<div ref="chartEl" class="chart"></div>
</div>
</div>
<div class="card">
<h3 class="card-title">整体概览</h3>
<div v-if="statsLoading" class="page-hint">加载中...</div>
@@ -30,7 +21,9 @@
</div>
<div class="stats-item">
<div class="stats-label">已通过</div>
<div class="stats-value stats-value-approved">{{ statsSummary.approved }}</div>
<div class="stats-value stats-value-approved">
{{ statsSummary.approved }}
</div>
</div>
<div class="stats-item">
<div class="stats-label">待审核</div>
@@ -38,12 +31,23 @@
</div>
<div class="stats-item">
<div class="stats-label">已拒绝</div>
<div class="stats-value stats-value-rejected">{{ statsSummary.rejected }}</div>
<div class="stats-value stats-value-rejected">
{{ statsSummary.rejected }}
</div>
</div>
</div>
</div>
</div>
<div class="card">
<h3 class="card-title">最近 7 天评论数趋势</h3>
<div v-if="statsLoading" class="page-hint">加载中...</div>
<div v-else-if="statsError" class="page-error">{{ statsError }}</div>
<div v-else class="chart-wrapper">
<div ref="chartEl" class="chart"></div>
</div>
</div>
<div class="card">
<h3 class="card-title">按域名统计</h3>
<div v-if="statsLoading" class="page-hint">加载中...</div>