feat(analytics): 扩展页面访问统计接口并新增站点隔离文档
- 在 `/admin/analytics/pages` 接口响应中添加 `itemsByPv` 和 `itemsByLatest` 字段,分别返回按访问量和最新访问排序的前20条数据,优化前端数据展示逻辑 - 前端管理后台适配新的接口响应结构,提升页面访问统计页面的性能和用户体验 - 新增站点隔离配置文档 (`/docs/config/site-isolation.md`),说明如何通过 `siteId` 配置实现数据隔离 - 在前端配置指南中补充 `siteId` 配置示例 - 新增常见问题文档 (`/docs/common-problems.md`),解答设置 `siteId` 后评论数据不显示的问题及数据迁移方案 - 在导航栏和侧边栏添加“常见问题”和“配置”相关入口,完善文档结构 - 修复前端组件 API 调用中 `postSlug` 参数可能为 `postUrl` 的兼容性问题
This commit is contained in:
@@ -263,22 +263,15 @@ export const getVisitPages = async (c: Context<{ Bindings: Bindings }>) => {
|
||||
const rawDomain = c.req.query('domain') || '';
|
||||
const domainFilter = rawDomain.trim().toLowerCase();
|
||||
const rawOrder = c.req.query('order') || '';
|
||||
const order = rawOrder.trim().toLowerCase();
|
||||
const isLatest = order === 'latest';
|
||||
const order = rawOrder.trim().toLowerCase() === 'latest' ? 'latest' : 'pv';
|
||||
|
||||
await c.env.CWD_DB.prepare(
|
||||
'CREATE TABLE IF NOT EXISTS page_stats (id INTEGER PRIMARY KEY AUTOINCREMENT, post_slug TEXT UNIQUE NOT NULL, post_title TEXT, post_url TEXT, pv INTEGER NOT NULL DEFAULT 0, last_visit_at INTEGER, created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL)'
|
||||
).run();
|
||||
|
||||
let sql =
|
||||
'SELECT post_slug, post_title, post_url, pv, last_visit_at FROM page_stats ORDER BY pv DESC, last_visit_at DESC';
|
||||
|
||||
if (isLatest) {
|
||||
sql =
|
||||
'SELECT post_slug, post_title, post_url, pv, last_visit_at FROM page_stats ORDER BY last_visit_at DESC, pv DESC';
|
||||
}
|
||||
|
||||
const { results } = await c.env.CWD_DB.prepare(sql).all<{
|
||||
const { results } = await c.env.CWD_DB.prepare(
|
||||
'SELECT post_slug, post_title, post_url, pv, last_visit_at FROM page_stats'
|
||||
).all<{
|
||||
post_slug: string;
|
||||
post_title: string | null;
|
||||
post_url: string | null;
|
||||
@@ -307,9 +300,44 @@ export const getVisitPages = async (c: Context<{ Bindings: Bindings }>) => {
|
||||
});
|
||||
}
|
||||
|
||||
items = items.slice(0, 20);
|
||||
const itemsByPv = items
|
||||
.slice()
|
||||
.sort((a, b) => {
|
||||
if (b.pv !== a.pv) {
|
||||
return b.pv - a.pv;
|
||||
}
|
||||
const aLast = a.lastVisitAt ?? 0;
|
||||
const bLast = b.lastVisitAt ?? 0;
|
||||
return bLast - aLast;
|
||||
})
|
||||
.slice(0, 20);
|
||||
|
||||
return c.json({ items });
|
||||
const itemsByLatest = items
|
||||
.slice()
|
||||
.sort((a, b) => {
|
||||
const aLast = a.lastVisitAt ?? 0;
|
||||
const bLast = b.lastVisitAt ?? 0;
|
||||
if (bLast !== aLast) {
|
||||
return bLast - aLast;
|
||||
}
|
||||
return b.pv - a.pv;
|
||||
})
|
||||
.slice(0, 20);
|
||||
|
||||
const response =
|
||||
order === 'latest'
|
||||
? {
|
||||
items: itemsByLatest,
|
||||
itemsByPv,
|
||||
itemsByLatest
|
||||
}
|
||||
: {
|
||||
items: itemsByPv,
|
||||
itemsByPv,
|
||||
itemsByLatest
|
||||
};
|
||||
|
||||
return c.json(response);
|
||||
} catch (e: any) {
|
||||
return c.json(
|
||||
{ message: e.message || '获取页面访问统计失败' },
|
||||
|
||||
Reference in New Issue
Block a user