feat(stats): 新增公开数据页 /stats,入口收敛到页脚

首页底部那张「站点统计」卡片下线,完整数据移到公开只读页 /stats:
今日实时数、概览六格、近 30 天折线与 12 个月柱状、三个占比环、
7×24 时段热力图、提问字数与回答耗时分布。

- 聚合在 internal/db/analytics.go(SUM(CASE WHEN),方言差异收敛在 analyticsDialectFor)
- 结果按自然日缓存,跨日重算一次后全站共用;重算失败降级返回上一份快照
- 图表零前端依赖:服务端算坐标的 SVG + CSS grid,禁用 JS 页面仍完整
- 环比取「上月 vs 上上月」:本月未过完,否则每月 1 号会得出 -95%
- 入口只在页脚「社区规则」与「找站长」之间;route.Home 不再计算统计
- 补 questions(created_at) 索引;启动后异步预热当天快照
- 测试:analytics 连真库验证软删除不计入、分桶下标、DOW 对齐
This commit is contained in:
tamakyi
2026-10-24 00:57:08 +08:00
parent c680671b7e
commit a5441c99fd
25 changed files with 2280 additions and 80 deletions
+77
View File
@@ -950,4 +950,81 @@ var zhTWDict = map[string]string{
"theme.name.sakura": "櫻花",
"theme.name.shiroko": "砂狼白子",
"theme.name.new-sakura": "新·櫻花",
// 全站數據頁(/stats):只顯示彙總數字,不含任何單則內容
"site.footer.stats": "數據",
"stats.title": "全站數據",
"stats.lead": "這裡只有彙總後的數字:全站收到多少提問、回答得有多快、大家習慣什麼時候來。不含任何一則具體提問的內容、提問者身分或來源位址。",
"stats.unavailable": "數據暫時無法使用,稍後再重新整理看看。",
"stats.today.questions": "今日提問",
"stats.today.answers": "今日回答",
"stats.today.tag": "(即時)",
"stats.kpi.users": "註冊使用者",
"stats.kpi.questions": "累計提問",
"stats.kpi.answered": "已回答",
"stats.kpi.answerRate": "回答率",
"stats.kpi.activeBoxes": "收到過提問的箱子",
"stats.kpi.messages": "累計私聊訊息",
"stats.insight.title": "數據速覽",
"stats.insight.note": "下面幾句是直接從上面的數字讀出來的,沒有推測。",
"stats.insight.empty": "提問數據還太少,暫時看不出什麼。",
"stats.insight.daily30": "近 30 天共收到 %s 則提問,日均 %.1f 則。",
"stats.insight.peak": "最忙的一天是 %s,收到 %s 則提問。",
"stats.insight.busiest": "提問最集中在 %s %d 點前後。",
"stats.insight.mom": "上月提問量比前一個月 %s%%。",
"stats.insight.fastReply": "已回答的提問中,%s%% 在 24 小時內得到回覆。",
"stats.insight.private": "%s%% 的提問選擇了私密(不公開)。",
"stats.trend.dailyTitle": "近 30 天提問趨勢",
"stats.trend.dailyNote": "依天統計的提問量。",
"stats.trend.monthlyTitle": "近 12 個月提問量",
"stats.trend.monthlyNote": "最後一根柱子是當月,還沒過完。",
"stats.mix.title": "組成",
"stats.mix.note": "三組比例:公開還是私密、有沒有被回答、提問者有沒有登入。",
"stats.mix.public": "公開提問",
"stats.mix.answered": "已回答",
"stats.mix.login": "登入使用者提問",
"stats.heat.title": "一週內的提問時段",
"stats.heat.note": "最近 %d 天的提問依「星期 × 小時」彙總,顏色越深表示越集中。",
"stats.heat.less": "少",
"stats.heat.more": "多",
"stats.content.title": "內容與節奏",
"stats.content.note": "提問有多長,回答有多快。",
"stats.content.lengthTitle": "提問字數分布",
"stats.content.replyTitle": "回答耗時分布",
"stats.len.1": "20 字以內",
"stats.len.2": "20–49 字",
"stats.len.3": "50–99 字",
"stats.len.4": "100–199 字",
"stats.len.5": "200–499 字",
"stats.len.6": "500 字以上",
"stats.reply.1": "1 小時內",
"stats.reply.2": "1–6 小時",
"stats.reply.3": "6–24 小時",
"stats.reply.4": "1–3 天",
"stats.reply.5": "3–7 天",
"stats.reply.6": "7 天以上",
"stats.wd.1": "一",
"stats.wd.2": "二",
"stats.wd.3": "三",
"stats.wd.4": "四",
"stats.wd.5": "五",
"stats.wd.6": "六",
"stats.wd.7": "日",
"stats.foot.dataDate": "數據基準日:",
"stats.foot.updated": "計算於",
"stats.foot.prevMonth": "最後一則提問:",
"stats.foot.prevAnswer": "最後一則回答:",
"stats.foot.privacy": "所有數字均為彙總結果,不展示單則提問內容、提問者身分或來源位址。",
"stats.foot.cacheNote": "累計數字與圖表是當日 0 點的快照,每天只更新一次;「今日」兩項為即時數字。",
}