feat: 每日热点问题共享库(定时生成+管理员手动更新+点击埋点)
CI / 后端测试 (push) Has been cancelled
CI / 前端构建 (push) Has been cancelled

数据库:
- daily_topics表:每天每场景一条热点问题记录
- sample_clicks表:记录用户点击示例问题行为

后端:
- DailyTopicStore: CRUD + 埋点 + 点击统计
- generate_daily_topics: AI生成4场景各25-30个问题
- 定时任务:每天凌晨3点自动生成(后台线程轮询)
- GET /topics/daily: 获取当天热点(公开)
- POST /topics/click: 点击埋点
- GET /admin/daily-topics: 管理端查看
- POST /admin/daily-topics: 管理员手动更新
- POST /admin/daily-topics/generate: 手动触发AI生成
- GET /admin/sample-clicks: 点击统计

前端:
- ChatPanel挂载时取当天热点,无则用硬编码兜底
- 点击示例问题时记录埋点
- AdminDailyTopics管理页面:查看/编辑/手动生成
- 路由 /admin/daily-topics + 导航配置

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
selfrelease
2026-08-31 17:04:33 +08:00
co-authored by Devin
parent 35cc6e54ea
commit a7ef530841
9 changed files with 638 additions and 3 deletions
+15 -1
View File
@@ -400,6 +400,17 @@ export function ChatPanel({
useEffect(() => {
setDynamicSamples(samples)
}, [samples])
/** 挂载时取当天热点问题,有则覆盖兜底示例 */
useEffect(() => {
api.getDailyTopics(scene)
.then((res) => {
if (res.questions?.length > 0) {
setDynamicSamples(res.questions)
}
})
.catch(() => {/* 用兜底示例 */})
}, [scene])
const [destroying, setDestroying] = useState(false)
/** 恢复历史中(从 ?sid= 断点续接) */
const [restoringHistory, setRestoringHistory] = useState(false)
@@ -1008,7 +1019,10 @@ export function ChatPanel({
<div className="py-2">
<div className="flex flex-wrap items-center gap-2">
{dynamicSamples.map((s) => (
<Button key={s} variant="outline" size="sm" onClick={() => setQuestion(s)} className="text-xs">
<Button key={s} variant="outline" size="sm" onClick={() => {
setQuestion(s)
api.recordSampleClick(scene, s).catch(() => {})
}} className="text-xs">
{s}
</Button>
))}