Skip to content

v1.2.0 — Feed / 点赞 / 草稿云同步 / 定时发布 / 限流 / MCP / 日志系统

Choose a tag to compare

@imqi1-github imqi1-github released this 06 Oct 09:38
· 19 commits to master since this release

🎉 新功能

📡 RSS Feed 体系

  • 新增分类订阅 /feed/category/:slug、标签订阅 /feed/tag/:slug、文章评论订阅 /feed/comments/:cid
  • 对应前台页面 head 自动注入 <link rel="alternate">,阅读器一键订阅
  • 主 Feed 重构为共享 helper,统一 RSS 2.0 + Media RSS 输出

❤️ 文章点赞

  • 前台点赞按钮:心形填充 + pulse + 8 粒子迸发动画,带 tooltip
  • 公开 API:IP+UA SHA256 指纹去重,复合唯一约束防并发写穿,Redis 5 分钟限速
  • 点赞数全站展示:首页/归档/分类/标签/搜索/文章详情 + 批量接口 /api/likes/counts
  • 后台文章管理新增「点赞数」列,点击查看明细 Dialog,支持单条删除(清理刷赞)
  • 点赞变更自动失效相关 ISR 缓存

📝 草稿云端同步

  • 编辑文章时每 30s 自动将正文 PATCH 到服务端,换设备/清缓存不丢稿
  • 仅同步 content 字段,不覆盖标题/分类/封面等元数据

⏰ 定时发布

  • 文章编辑页新增「定时发布」时间控件
  • Nitro 内置 cron 插件每分钟扫描,到点自动发布并失效前台缓存

🛡️ API 限流中间件

  • 覆盖评论发布/点赞/验证码/搜索/友链申请/邮件/错误上报 7 类端点
  • 429 + 标准 Retry-After / X-RateLimit-* 响应头;Redis 优先、内存兜底、异常 fail-open

🤖 MCP Server

  • POST /api/mcp 暴露 5 个只读工具:搜索文章/读正文/最新列表/分类/标签
  • 供 Claude / Cursor 等 AI 客户端检索站点内容;严格白名单,无任何写工具
  • 新增 5 个运维诊断工具:系统健康快照/结构化日志读取/内容数据概览/Redis 缓存诊断/缓存清理
  • 运维工具由 MCP_OPS_TOKEN 门禁(fail-closed,timingSafeEqual 校验),清理类操作须显式 confirm
  • 修复中文入参 mojibake:readRawBody 二进制模式双重编码导致中文搜索恒为空,改为 Buffer 直传

📋 日志系统

  • 统一日志工具:8 分类(访问/审计/认证/外部/缓存/限流/任务/监控)
  • console 与文件双写,按天落地 LOG_DIR/<分类>/<日期>.log(LOG_DIR 环境变量可配)
  • 行内中文标签,logWithCaller() 可附带文件:行号
  • 全量接入:登录/2FA/登出、24 处后台写操作审计、COS 上传删除、外联 fetch、缓存失效、限流命中、定时任务
  • 原邮件日志迁入统一体系;错误监控:5xx 拦截 → 日志 + 邮件通知站主(5 分钟抑制防刷屏)

🔔 邮件通知细分开关

  • 「通知站长」总开关下新增三个子开关(默认开,与既有行为一致):错误监控 / 评论通知 / 友链申请通知
  • 语义:总开关关 → 一律不发;子开关关 → 对应类别不发;「回复评论者」通知不受此管
  • 后台设置页呈现为总开关 + 缩进子开关,总开关关闭时子区置灰

🔧 优化与修复

  • 前台 SSR 化:全站导航/热力图/相关文章改用 useFetch,首屏零 API 请求、控制台干净
  • 测试库隔离:bun preload 强制测试连 imqi1_test,根除测试误清开发库数据的问题
  • 测试 mock 修复:test/helpers/fake-prisma.ts 补 isPrismaUniqueConstraintError 导出,修 bun run test 的 1 fail + 1 error(server/utils/rss.ts、server/api/contents/likes/[cid].post.ts 已切到该函数的 duck-type 检测)
  • 依赖显式声明:postgres-array@3.0.4 加入 dependencies,防 npm prune / 部分上传导致生产机报 ERR_MODULE_NOT_FOUND(原作为 @prisma/adapter-pg 的 transitive dep,某些安装路径会漏掉)
  • 构建产物软链解实:nft 会把部分依赖软链到 .nitro/ 缓存目录,SFTP 上传后软链悬空 → 生产 502;构建后递归全树把软链替换为真实目录(嵌套 7 处,含 /feed 500 的根因)
  • 验证码:保持 4 字符可读性,增强干扰(曲线笔触/高密度噪点/字符粘连/±35° 旋转)
  • 登录密码错误后立即显示并刷新验证码
  • 搜索页骨架屏与真实结果对齐;后台文章管理骨架屏列宽/内边距对齐
  • file-server 日志 ANSI 彩色输出(TTY 检测,管道自动降级)
  • 错误通知邮件中文化

⚠️ BREAKING CHANGES 与数据库迁移

  • 后台「记录邮件日志」开关移除,邮件日志始终记录
  • error_logs 表不再创建(错误监控改为日志 + 邮件)

数据库升级(v1.1.5 → v1.2.0)需手动执行以下 SQL(init-db.sql 仅用于空库初始化,不在旧库上运行):

-- 1) 点赞表
CREATE TABLE "likes" (
  "id" SERIAL NOT NULL,
  "cid" INTEGER NOT NULL,
  "fingerprint" VARCHAR(64) NOT NULL,
  "ip" VARCHAR(45),
  "user_agent" VARCHAR(255),
  "create_time" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY ("id"),
  CONSTRAINT "Likes_cid_fkey" FOREIGN KEY ("cid") REFERENCES "contents"("cid") ON DELETE CASCADE ON UPDATE CASCADE
);
CREATE UNIQUE INDEX "Likes_cid_fingerprint_key" ON "likes"("cid", "fingerprint");
CREATE INDEX "Likes_cid_create_time_idx" ON "likes"("cid", "create_time");

-- 2) 定时发布
ALTER TABLE "contents" ADD COLUMN "scheduled_at" TIMESTAMP(3);
CREATE INDEX "Contents_status_scheduled_at_idx" ON "contents"("status", "scheduled_at");

Full Changelog: https://github.com/imqi1-github/imqi1-cms/releases/tag/v1.1.5