# 历史记录按天去重功能实现计划 ## 需求总结 当用户在**同一天内**重复点击同一个实用工具或API界面时,不创建新的历史记录,而是**更新已有记录的浏览时间**。 ## 当前状态分析 ### 前端(useRecordHistory.ts) - 使用 `useRef` 实现2秒防抖 - **问题**:只在同一组件实例内有效,组件卸载后状态丢失,无法跨导航去重 ### 后端(history/serializers.py) - `BrowsingHistoryCreateSerializer.create()` 已有去重逻辑 - 查询一小时内是否有相同 `user + link` 的记录 - 如果有,调用 `existing.save()` 更新 `viewed_at`(因为 `auto_now=True`) - **问题**:时间窗口是1小时,不是按天 ## 实现方案 ### 1. 前端修改:`src/hooks/useRecordHistory.ts` **目标**:使用 localStorage 实现跨组件/跨导航的按天去重 **修改内容**: - 添加 `getDailyKey(type, link)` 函数,生成格式为 `history:{type}:{link}:{YYYY-MM-DD}` 的 key - 添加 `isRecordedToday(type, link)` 函数,检查 localStorage 中是否已存在当天记录 - 添加 `markAsRecorded(type, link)` 函数,在 localStorage 中标记已记录 - 在 `useEffect` 中,先检查 `isRecordedToday`,如果已记录则不发送请求 - 发送请求成功后,调用 `markAsRecorded` 标记 **localStorage 设计**: - Key: `history:{type}:{link}:{YYYY-MM-DD}` - Value: 时间戳或简单标记 `"1"` - 示例: `history:tool:/utility/qrcode-generator:2026-07-28` ### 2. 后端修改:`history/serializers.py` **目标**:将去重逻辑从"一小时内"改为"当天内" **修改内容**: - 修改 `BrowsingHistoryCreateSerializer.create()` 方法 - 将 `one_hour_ago = timezone.now() - timedelta(hours=1)` 改为当天开始时间 - 使用 `viewed_at__date=timezone.now().date()` 匹配当天记录 - 查询条件:`user=user, link=link, viewed_at__date=today` - 如果找到当天记录,调用 `existing.save()` 更新 `viewed_at` - 如果没有,创建新记录 ### 3. 不需要修改的文件 - `history/models.py` - 模型定义无需修改 - `history/views.py` - 视图逻辑无需修改,serializer 已处理去重 - `history/urls.py` - URL 配置无需修改 ## 涉及文件 | 文件 | 修改类型 | 说明 | |------|----------|------| | `src/hooks/useRecordHistory.ts` | 修改 | 添加 localStorage 按天去重逻辑 | | `chunyu_project/history/serializers.py` | 修改 | 将去重时间窗口从1小时改为当天 | ## 验证步骤 1. **同一天内重复点击测试** - 打开同一个工具/API 页面3次 - 检查历史记录页面,应只有1条记录 - 检查 localStorage,应有对应的 key 2. **跨天测试** - 第一天点击工具A,记录历史 - 第二天再次点击工具A - 检查历史记录页面,应有2条记录(分别在不同日期) 3. **不同工具测试** - 同一天内点击工具A、工具B、工具C - 检查历史记录页面,应有3条记录 4. **localStorage 清理测试** - 确认不会无限增长(每天自动覆盖旧日期的 key) ## 风险评估 - localStorage 被用户清除时,去重会失效,但后端仍有兜底逻辑 - 后端修改不影响现有API接口,只是调整了去重时间窗口