fix(admin): 修复按站点筛选时统计数据计算错误
之前当提供 siteId 参数时,SQL 查询会添加 WHERE 子句进行过滤,导致 domains 数据也只包含该站点的评论,这与预期行为不符。预期是 domains 应始终返回所有站点的统计数据,而 summary 才根据 siteId 进行过滤。 现在改为始终查询所有评论,然后在内存中根据 siteId 过滤 rowsForSummary 以计算 summary,确保 domains 包含全局数据。
This commit is contained in:
92
cwd-api/src/api/admin/getStats.spec.ts
Normal file
92
cwd-api/src/api/admin/getStats.spec.ts
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
import { describe, it, expect, vi } from 'vitest';
|
||||||
|
import { getStats } from './getStats';
|
||||||
|
|
||||||
|
describe('getStats siteId filtering behavior', () => {
|
||||||
|
const createMockContext = (rows: any[], siteId?: string) => {
|
||||||
|
const allMock = vi.fn().mockResolvedValue({ results: rows });
|
||||||
|
const prepareMock = vi.fn().mockReturnValue({
|
||||||
|
all: allMock
|
||||||
|
});
|
||||||
|
|
||||||
|
const c = {
|
||||||
|
req: {
|
||||||
|
query: (key: string) => {
|
||||||
|
if (key === 'siteId') return siteId;
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
env: {
|
||||||
|
CWD_DB: {
|
||||||
|
prepare: prepareMock
|
||||||
|
}
|
||||||
|
},
|
||||||
|
json: vi.fn()
|
||||||
|
} as any;
|
||||||
|
|
||||||
|
return { c, prepareMock, allMock };
|
||||||
|
};
|
||||||
|
|
||||||
|
it('returns global domains while summary is filtered by siteId', async () => {
|
||||||
|
const now = Date.now();
|
||||||
|
const baseDay = new Date(now);
|
||||||
|
baseDay.setUTCHours(0, 0, 0, 0);
|
||||||
|
const today = baseDay.getTime();
|
||||||
|
|
||||||
|
const rows = [
|
||||||
|
{
|
||||||
|
created: today,
|
||||||
|
status: 'approved',
|
||||||
|
site_id: 'blog'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
created: today,
|
||||||
|
status: 'pending',
|
||||||
|
site_id: 'docs'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
created: today,
|
||||||
|
status: 'rejected',
|
||||||
|
site_id: ''
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const { c } = createMockContext(rows, 'blog');
|
||||||
|
|
||||||
|
await getStats(c);
|
||||||
|
|
||||||
|
expect(c.json).toHaveBeenCalledTimes(1);
|
||||||
|
const response = (c.json as any).mock.calls[0][0];
|
||||||
|
|
||||||
|
expect(response.summary).toEqual({
|
||||||
|
total: 1,
|
||||||
|
approved: 1,
|
||||||
|
pending: 0,
|
||||||
|
rejected: 0
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(response.domains).toEqual([
|
||||||
|
{
|
||||||
|
domain: 'blog',
|
||||||
|
total: 1,
|
||||||
|
approved: 1,
|
||||||
|
pending: 0,
|
||||||
|
rejected: 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
domain: 'docs',
|
||||||
|
total: 1,
|
||||||
|
approved: 0,
|
||||||
|
pending: 1,
|
||||||
|
rejected: 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
domain: 'default',
|
||||||
|
total: 1,
|
||||||
|
approved: 0,
|
||||||
|
pending: 0,
|
||||||
|
rejected: 1
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
@@ -17,15 +17,9 @@ export const getStats = async (c: Context<{ Bindings: Bindings }>) => {
|
|||||||
const rawSiteId = c.req.query('siteId');
|
const rawSiteId = c.req.query('siteId');
|
||||||
const siteId = rawSiteId && rawSiteId !== 'default' ? rawSiteId : null;
|
const siteId = rawSiteId && rawSiteId !== 'default' ? rawSiteId : null;
|
||||||
|
|
||||||
let sql = 'SELECT created, status, site_id FROM Comment';
|
const { results } = await c.env.CWD_DB.prepare(
|
||||||
const params: any[] = [];
|
'SELECT created, status, site_id FROM Comment'
|
||||||
|
).all<{
|
||||||
if (siteId) {
|
|
||||||
sql += ' WHERE site_id = ?';
|
|
||||||
params.push(siteId);
|
|
||||||
}
|
|
||||||
|
|
||||||
const { results } = await c.env.CWD_DB.prepare(sql).bind(...params).all<{
|
|
||||||
created: number;
|
created: number;
|
||||||
status: string;
|
status: string;
|
||||||
site_id: string | null;
|
site_id: string | null;
|
||||||
@@ -65,7 +59,16 @@ export const getStats = async (c: Context<{ Bindings: Bindings }>) => {
|
|||||||
} else if (row.status === 'rejected') {
|
} else if (row.status === 'rejected') {
|
||||||
counts.rejected += 1;
|
counts.rejected += 1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const rowsForSummary = siteId
|
||||||
|
? results.filter((row) => {
|
||||||
|
const key = row.site_id && row.site_id.trim() ? row.site_id.trim() : 'default';
|
||||||
|
return key === siteId;
|
||||||
|
})
|
||||||
|
: results;
|
||||||
|
|
||||||
|
for (const row of rowsForSummary) {
|
||||||
summary.total += 1;
|
summary.total += 1;
|
||||||
if (row.status === 'approved') {
|
if (row.status === 'approved') {
|
||||||
summary.approved += 1;
|
summary.approved += 1;
|
||||||
|
|||||||
Reference in New Issue
Block a user