跳转至

后端-数据库-新闻删除后收藏未级联清理

问题现象

  • 收藏列表第2页点击"加入卡片"提示"操作失败"(第1页正常)
  • 服务器日志显示 GET /api/news/web/2334/card 404 Not Found(news_id 不存在)
  • 影响范围:19 条收藏(18 web + 1 wechat)的引用新闻已被删除

核心问题

  1. 数据孤岛web_news 表 ID 2300-2700 范围的全部记录被删除(推测原因:站点删除重建或 cleanup_duplicate_news.py --fix 去重),但 favorites 表保留了这些已删除新闻的引用,形成孤儿记录

  2. 缺少级联清理

  3. SiteService.delete() 只删除 site 记录,不清理关联的 web_newsfavorites
  4. cleanup_duplicate_news.py --fix 删除重复 news 时,不清理对应的 favorites

  5. 错误信息被吞没:axios 404 拦截器将原始 AxiosError 替换为 new Error('接口不存在(404)'),丢失 response.data.detail;前端 handleJoinCard 未捕获 e.message,只显示"操作失败"

查询孤儿收藏的 SQL

SELECT f.id, f.news_id, f.news_type, f.title
FROM favorites f
LEFT JOIN web_news w ON f.news_id = w.id AND f.news_type = 'web'
LEFT JOIN wechat_articles a ON f.news_id = a.id AND f.news_type = 'public_account'
WHERE (f.news_type = 'web' AND w.id IS NULL)
   OR (f.news_type = 'public_account' AND a.id IS NULL);

解决方法

1. 清理孤儿数据(生产服务器)

ssh news
cd /www/news
source venv/bin/activate
python3 -c "
from sqlalchemy import create_engine, text
from dotenv import load_dotenv; import os
load_dotenv()
# ... 执行上面 SQL 的 DELETE 版本
"

2. 修复级联删除(代码层)

  • modules/web-crawler/service.pySiteService.delete() 删除 site 前先查 WebNews.site_id,然后删除对应 favorites 和 news
  • src/cli/cleanup_duplicate_news.py:删除重复 web_news 和 wechat_articles 前先清理 favorites

3. 收藏列表自动过滤孤儿

  • src/service/favorite_service.pyget_list() 使用 EXISTS 子查询,只返回 news 真实存在的收藏

4. 前端错误提示优化

  • web/src/api/request.ts:404 拦截器保留 response.data.detailError.message
  • web/src/views/Favorites.vuehandleJoinCardremoveFavorite 显示 e.message

下次防错措施

  • 快速定位:看到"操作失败"且日志有 404 on /api/news/*/card,立即查上面孤儿 SQL
  • 部署后巡检:每次站点删除或 dedup 脚本执行后,运行孤儿查询确认 count = 0
  • 流程改进:站点管理中删除站点时弹窗提示"将同时删除 N 条新闻和 M 条收藏"