# 更新日志 ## v1.2.1 > 2026-07-01 ### Bug 修复 - **修复 `AiReplyOrchestrator.retryOrFail` 重试计数失效** — `.then()` 丢弃了更新后的记录导致 `retryCount` 始终为 0,AI 生成失败时陷入无限重试。改为 `.flatMap()` 传递更新后的记录 - **修复误报反馈"AI 回复"被空字符串覆盖** — `.subscribe()` 在异步流程中过早触发,导致 AI 回复生成完成后被空字符串覆盖。改为在 `.doOnSuccess()` 中触发异步生成 - **修复 `PersonaResolver` 在响应式上下文中使用 `.block()`** — 调用阻塞方法会阻塞 Reactor 线程。改为返回 `Mono` 并使用 `Flux.concatMap().next()` 替代 for 循环 - **修复 `penalizeComment`/`penalizeReply` 缺少乐观锁重试** — 并发更新 Comment/Reply 时可能静默失败。添加 `Retry.backoff(3, 100ms)` 重试 - **修复 `approveOriginalComment` 缺少乐观锁重试** — 同上,添加 `Retry.backoff(3, 100ms)` 重试 - **修复误报反馈端点无法重试 `FAIL` 状态记录** — 仅接受 `FILTERED` 和 `FALSE_POSITIVE` 状态,AI 生成失败的记录无法重试。现接受 `FAIL` 状态 - **修复 `tag-NEUTRAL` 缺少 CSS 样式** — 中性情感标签无样式显示。补充样式定义 - **修复 `handleTriggerAiReply` 缺少加载保护** — 触发 AI 回复按钮可被重复点击导致重复提交。添加 loading 状态 - **修复 `filterKeyword` 输入未做防抖** — 每次按键都触发搜索,性能开销大。添加 300ms 防抖 - **修复 `performCleanup` 逻辑错误** — 清理逻辑存在判断错误 ### 改进 - **优化 `extractChoice` 分类匹配优先级** — 优先匹配违规类别(advertising/abuse/sensitive/meaningless),再匹配 `normal`,避免正常评论被误判为违规类别 --- ## v1.2.0 > 2026-06-25 ### 新增 - **误报反馈功能** — 被拦截的评论可进行误报反馈,支持两种处理方式: - **AI 回复**:标记为通过 + 触发 AI 生成回复 - **仅通过**:仅标记为通过,不生成回复 - **误报通过状态** — 新增 `FALSE_POSITIVE` 状态,"仅通过"的记录显示为"误报通过",不显示"通过/拒绝"按钮 - **触发 AI 回复按钮** — "误报通过"状态的记录可随时点击"触发AI回复"按钮补生成 AI 回复 - **上下文优先判断原则** — 前置过滤 AI 提示词重写,遵循五条核心原则:上下文优先、口语化宽容、恶意导向判定、宁放勿杀、闲聊不算无意义 ### Bug 修复 - **修复误报反馈"AI 回复"被前置过滤再次拦截** — `processComment()` 始终调用 `preFilterService.check()`,用户已确认为误报的评论会被再次拦截。新增 `processFalsePositive()` 方法跳过前置过滤和去重检查 - **修复误报反馈"AI 回复"被去重检查拦截** — `hasExistingReply()` 找到已有的 FILTERED→PENDING 记录导致 AI 回复无法生成。`processFalsePositive()` 复用已有记录,不经过去重检查 - **修复误报反馈"AI 回复"导致全站崩溃** — `processComment()` 同步等待 AI 生成完成,HTTP 请求长时间不返回。改为 `.subscribe()` 异步执行,API 立即返回 - **修复误报反馈"仅通过"后显示通过/拒绝按钮** — "仅通过"将记录设为 `status=PASS, published=false, reply=""`,导致显示"通过/拒绝"按钮且内容为空。改为 `status=FALSE_POSITIVE` - **修复 `extractChoice` 无匹配时返回原始文本** — AI 返回非预期文本时被误判为违规类别。改为返回空字符串触发安全拦截 - **修复 `approveOriginalComment` 缺少乐观锁重试** — 并发更新 Comment/Reply 时可能静默失败。添加 `Retry.backoff(3, 100ms)` 重试 ### 改进 - **消除 `checkBlockedCommenters` 重复代码** — `FilterService` 新增 `isCommenterBlocked(commentName)` 公共方法,`AiReplyOrchestrator` 改为调用它 - **前端批量操作防重复提交** — 批量通过/拒绝/删除按钮添加 `batchLoading` 状态,操作期间禁用按钮 --- ## v1.1.2 > 2026-06-24 ### Bug 修复 - **修复 AI 分类完全不可用** — `classifyWithChoice` 和 `classifyWithChat` 均使用了 `GenerateTextRequest.Builder.system()` 方法,而该方法在当前 AI Foundation 版本中不被支持或导致运行时错误,导致所有评论均被拦截并显示"AI分类服务不可用,安全拦截"。现改为将 system prompt 合并到 user prompt 中,与可用的 `chat()` 方法保持一致的调用方式 - **修复 `classifyWithChoice` NPE** — `.map()` 返回 `null` 时触发 Reactor 内部 NullPointerException,改为 `.flatMap()` + `Mono.empty()` 正确触发 fallback ### 改进 - **分类调用诊断日志增强** — 在 `AiFoundationDelegate`、`AiFoundationClient`、`CommentPreFilterService` 中增加关键诊断日志(分类开始、fallback 触发、分类结果、异常详情),便于排查分类链路问题 - **AI 分类空结果处理** — 当 AI 返回空字符串时单独拦截,区别于"服务不可用"场景 --- ## v1.1.1 > 2026-06-24 ### 改进 - **"无意义"分类范围收窄** — 与文章主题无关的闲聊、灌水、打招呼不再被判为"无意义",仅纯乱码和无意义字符堆砌(如随机符号、键盘乱敲)才归类为"无意义" - **AI 分类降级方案** — 当 `OutputSpec.choice` 结构化输出不被模型支持时,自动退回到普通 chat 调用并从响应文本中提取分类值(`classifyWithChat` fallback) --- ## v1.1.0 > 2026-06-23 ### 新增 - **评论前置过滤(合规检测)** — AI 回复前对评论进行合规性分类,识别广告/辱骂攻击/敏感内容/无意义内容,违规评论停止生成 AI 回复,节省 Token - **违规评论自动设为待审核** — 检测到违规评论时自动将原评论 `approved` 置为 `false`,进入待审核队列,前端不再展示该评论 - **FILTERED 日志状态** — 被拦截的评论生成"已拦截"状态记录,日志页支持按"已拦截"状态筛选 - **拦截原因分类标签** — 日志页显示拦截分类标签(广告/辱骂攻击/敏感内容/无意义)和详细拦截原因(含评论内容摘要) - **安全优先策略** — AI 分类服务不可用或异常时,默认拦截评论而非放行,防止违规内容漏网 ### 改进 - **AI Foundation 隔离加载** — 将 AI Foundation API 引用隔离到 `AiFoundationDelegate` 类,`AiFoundationClient` 不再直接引用 AI Foundation 类,修复未安装 AI Foundation 时插件无法启动的问题(`NoClassDefFoundError`) - **评论内容 HTML 剥离** — 前置过滤检测前自动剥离评论 HTML 标签,提升 AI 分类准确性 - **对话场景精准处罚** — AI 对话场景下违规内容来自 Reply 时,仅取消通过该 Reply 而非父级 Comment,避免误伤 - **升级配置自动迁移** — 从 v1.0.x 升级时自动将 `preFilterEnabled` 从 `false` 迁移为 `true`(新默认值) ### Bug 修复 - **修复未安装 AI Foundation 时插件无法启动** — `BeanDefinitionStoreException: Failed to parse AiFoundationClient`,将 AI Foundation API 引用隔离到委托类 - **修复前置过滤默认关闭** — `preFilterEnabled` 默认值从 `false` 改为 `true`,新安装和升级用户均默认启用 - **修复 `penalize()` 遗漏 `approved=null`** — Halo 评论创建时 `approved` 可能为 `null`,原代码仅处理 `approved=true` 的情况 - **修复 `classify()` 失败时放行违规评论** — `defaultIfEmpty` 和 `onErrorResume` 改为拦截而非放行 - **修复 Windows 构建失败** — Gradle Worker Daemon 执行 pnpm 退出码 268435659,改用系统 pnpm Exec 任务并禁用 Daemon --- ## v1.0.4 > 2026-06-19 ### 改进 - **对话弹窗头像显示** — 对话弹窗中每条消息显示 Gravatar 头像,基于评论者或 AI 角色的邮箱自动匹配 - **对话引用摘要** — 对话弹窗中回复消息显示引用摘要框,标明引用了谁的什么内容,支持截断显示 - **UI 全面重构** — LogsView 和 SettingsView 改用纯 Scoped CSS,移除所有 Tailwind 类和自定义 CSS 依赖,避免 Halo 主题冲突 - **标签去 Emoji 化** — 状态、情感标签改用纯色背景标签,去除所有 Emoji - **移动端适配优化** — 全面优化移动端响应式布局,解决排版错位问题 - **AI角色设置完善** — 支持 CRUD、Gravatar 头像预览、性别/唤醒词/默认角色配置 - **配置导入导出** — 支持将插件配置(ConfigMap + AI角色)导出为 JSON 文件,方便备份和迁移 - **评论者黑名单弹窗选择** — 设置页面可从已有评论列表中选择评论者添加到黑名单 ### Bug 修复 - **修复对话弹窗引用溯源** — 后端 `getConversation` 重写,构建 Reply 映射字典正确溯源引用关系 - **修复 ConversationMessage 数据结构** — 新增 `quoteOwner`/`quoteContent` 字段支持引用摘要展示 - **修复 AI 角色邮箱提取** — 后端新增 `extractOwnerEmail` 方法,正确从 CommentOwner 提取邮箱用于头像生成 --- ## v1.0.3 ### 改进 - **SettingsView 完整功能版** — 5个设置面板(基本设置、AI角色、模型设置、Prompt、数据清理)全部实现 - **AI角色管理** — 支持 CRUD、Gravatar 头像、性别/唤醒词/默认角色配置 - **数据清理** — 自动清理开关、保留天数滑块、手动清理 - **导入导出** — JSON 配置导入导出 - **评论者黑名单弹窗选择** — 从已有评论列表中选择评论者 --- ## v1.0.2 ### 改进 - **LogsView & SettingsView 样式重构** — 移除所有 Tailwind 类,改用 `