You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
9.1 KiB
9.1 KiB
设计:评论邮件配置与通知偏好
日期:2026-04-20
状态:已定稿(待实现计划)
1. 背景与目标
当前评论系统仅支持游客昵称与正文输入,不采集游客邮箱;登录用户评论流程也不与邮箱和通知偏好联动。本次需求是在不阻断评论核心体验的前提下,补齐评论邮件通知所需的最小闭环:
- 增加全局邮件发件配置(管理员可配置,默认未配置)。
- 游客评论默认要求填写邮箱,勾选匿名后邮箱可不填。
- 登录用户可自由评论;若没有邮箱,不阻断但不接收通知。
- 每个登录用户可自行配置是否接收评论邮件通知,默认开启。
- 管理员配置好发件参数后,可执行“测试发件”验证可用性。
2. 范围与非目标
2.1 本期范围
- 评论通知总开关与 SMTP 发件参数的全局配置。
- 游客评论表单新增邮箱与匿名逻辑。
- 用户通知偏好开关(用户级配置,默认开启)。
- 评论触发通知的基础发送策略(仅通知被回复评论作者)。
- 管理员测试发件接口与后台按钮。
2.2 非目标
- 不实现复杂通知订阅中心(如多事件类型细粒度订阅)。
- 不实现邮件模板系统化编辑器。
- 不实现消息队列重试平台;本期采用轻量失败记录与跳过策略。
- 不实现游客通知收件(游客仅作为评论发表者,不作为通知接收主体)。
3. 核心业务规则
3.1 游客评论规则
- 默认
guestIsAnonymous = false:guestEmail必填,且需通过邮箱格式校验。
- 当
guestIsAnonymous = true:guestEmail允许为空。
- 无论匿名与否,
guestDisplayName与body仍按现有规则校验。
3.2 登录用户评论规则
- 评论始终允许提交(不因邮箱缺失阻断)。
- 用户无邮箱时展示提示:“未填写邮箱将无法接收评论通知”。
- 用户关闭通知偏好时展示提示:“你已关闭评论邮件通知”。
3.3 通知触发与跳过规则
仅当以下条件全部满足时发送邮件:
- 全局
commentEmailNotifyEnabled = true。 - SMTP 全局配置完整且通过基础合法性检查。
- 目标接收用户
commentNotifyEnabled = true。 - 目标接收用户资料中存在有效邮箱。
- 事件存在有效通知对象(本期:被回复评论作者,且不是自己)。
任一条件不满足时直接跳过发送,不影响评论创建成功。
4. 数据模型与配置模型
4.1 全局配置新增键(global)
commentEmailNotifyEnabled:boolean,默认false。commentMailFromEmail:string,默认""。commentSmtpHost:string,默认""。commentSmtpPort:number,默认465。commentSmtpSecure:boolean,默认true。commentSmtpUser:string,默认""。commentSmtpPass:string,默认""。
校验约束:
commentSmtpPort:整数,范围1-65535。commentMailFromEmail:为空允许;非空时必须邮箱格式合法。- 其余字符串允许空(空表示未配置完成)。
4.2 用户级配置新增键(both)
commentNotifyEnabled:boolean,默认true,userOverridable = true。
说明:该项采用现有 global/user 覆盖机制,用户未设置时继承默认值 true。
4.3 评论表扩展
post_comments 新增字段:
guest_email:text,可空。guest_is_anonymous:boolean,非空,默认false。
服务层强制约束:
kind = "guest"且guest_is_anonymous = false时,guest_email必填且格式合法。kind = "guest"且guest_is_anonymous = true时,guest_email可空。kind = "user"时忽略游客邮箱与匿名字段(统一写入空值/默认值)。
5. API 与服务设计
5.1 评论创建接口扩展
沿用现有两个评论 POST 入口:
POST /api/public/profile/:publicSlug/posts/:postSlug/commentsPOST /api/public/unlisted/:publicSlug/:shareToken/comments
请求体扩展(仅对游客生效):
guestDisplayName: stringguestIsAnonymous?: boolean(默认false)guestEmail?: stringbody: string
服务端行为:
- 根据会话判定
kind,不信任客户端自报。 - 登录用户分支忽略
guestIsAnonymous与guestEmail。 - 游客分支按规则校验并入库。
5.2 通知发送服务
新增评论通知服务入口(命名可在实现计划定稿),在评论创建成功后触发。
本期通知对象策略:
- 仅在“回复评论”场景下,通知父评论对应的登录用户作者。
- 顶层评论不触发广播通知。
- 评论者与接收者相同则跳过(防止自通知)。
失败处理:
- 发送失败只记录日志,不回滚评论创建事务结果。
- 日志中包含
postId/commentId/receiverUserId/reason便于追踪。
5.3 管理员测试发件接口
新增管理员接口(建议):
POST /api/config/global/comment-email-test
行为:
- 要求管理员身份。
- 读取当前全局邮件配置,若配置不完整返回
400。 - 向“当前管理员账号邮箱”发送测试邮件;管理员无邮箱则返回
400。 - 成功返回
200与确认消息。
6. 前端交互设计
6.1 管理后台配置页
文件:app/pages/me/admin/config/index.vue(扩展现有页面)
新增“评论通知邮件”分组:
- 通知总开关。
- 发件人邮箱。
- SMTP 主机、端口、安全连接、用户名、密码。
- “发送测试邮件”按钮(仅在保存后可点,或点击时读取当前值直接测试)。
交互要求:
smtpPass输入框掩码显示。- 空配置允许保存。
- 当配置不完整时展示“未配置完成,无法发件”提示。
6.2 评论组件
文件:app/components/PostComments.vue(扩展游客表单)
游客态新增:
guestEmail输入框(默认必填)。匿名评论复选框(勾选后邮箱改为非必填)。
登录态新增:
- 若用户邮箱为空,显示提示文案。
- 若用户通知偏好关闭,显示提示文案。
6.3 用户设置页
在用户个人设置页增加:
接收评论邮件通知开关(默认开启)。
7. 错误处理与安全
- 评论接口输入校验失败:返回
400(保持现有错误风格)。 - 未登录访问管理员发件测试接口:
401/403。 - 邮件配置不完整触发测试:
400。 - 测试发件失败:返回
502或统一错误码,并记录服务端日志。 - 管理端展示配置时,
smtpPass不做明文回显(可回显占位符或保持空,提交时按“有改才覆盖”策略实现)。
8. 测试与验收
8.1 服务层/接口测试
- 游客评论:
- 非匿名 + 无邮箱 ->
400 - 非匿名 + 合法邮箱 ->
200 - 匿名 + 空邮箱 ->
200
- 非匿名 + 无邮箱 ->
- 登录用户无邮箱评论 ->
200(不阻断) - 通知开关关闭 -> 不触发发送
- 用户通知偏好关闭 -> 不触发发送
- 管理员测试发件:
- 配置不完整 ->
400 - 管理员无邮箱 ->
400 - 配置完整且邮箱存在 ->
200
- 配置不完整 ->
8.2 前端手动验收
- 管理员可保存评论邮件配置并看到状态提示。
- 配置完成后测试发件按钮可成功触发。
- 游客默认邮箱必填,勾选匿名后可不填邮箱发表评论。
- 登录用户无邮箱时出现提示但仍可评论。
- 用户可在设置页关闭通知并立即生效。
9. 实施顺序建议
- 扩展配置注册表与全局配置管理页。
- 扩展评论表结构与服务校验。
- 增加用户通知偏好配置与设置页开关。
- 接入通知发送服务与日志。
- 增加管理员测试发件接口与按钮。
- 完成测试与联调验收。
10. 数据库迁移回滚预案(Task4)
10.1 限制说明(SQLite)
- SQLite 不支持通用
DROP COLUMN语法,无法直接删除post_comments.guest_email与post_comments.guest_is_anonymous。 - 因此 Task4 回滚不能依赖“反向删列”语句,必须采用“建新表 + 搬迁 + 替换”的结构化回滚方案。
10.2 回滚执行前置条件
- 仅在维护窗口执行,暂停写入评论相关流量,避免迁移过程中出现并发写导致数据不一致。
- 执行前完成数据库备份(至少一份可恢复快照),并验证备份可用性后再开始回滚。
10.3 回滚步骤(可执行)
- 创建临时表(例如
post_comments_rollback),字段集合与回滚前结构一致,不包含guest_email、guest_is_anonymous。 - 将原
post_comments的保留字段按列名显式写入临时表(禁止SELECT *,避免列位错配)。 - 删除或重命名原
post_comments表。 - 将临时表重命名为
post_comments,完成结构替换。 - 按回滚前定义重建
post_comments相关索引、唯一约束与外键约束(如有)。 - 执行完整性校验(记录条数、关键查询、外键检查)并恢复流量。
10.4 风险与注意事项
- 回滚方案仅调整表结构,不应修改业务逻辑代码与已发布 migration 文件。
- 若任一步骤异常,立即停止后续操作,使用回滚前备份恢复并重新评估。