feat(admin): 添加评论按域名筛选功能并调整统计页面布局
- 在评论管理页面添加域名筛选功能 - 调整统计页面中卡片顺序,将图表移至概览下方 - 更新文档添加版本更新警告提示 - 修改评论列表API支持域名参数查询
This commit is contained in:
@@ -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 }> {
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user