5.8 KiB
5.8 KiB
Notify 产品与技术规格
目标与定位
- 目标:打造简洁明了、同时适配桌面与移动浏览器的提醒应用。
- 核心能力:Todo 与多用户提醒、周期性规则、提前提醒、网页通知 + Bark 推送。
需求澄清后的产品规格
核心对象
- Todo:个人待办,支持单次与周期性,配置一个或多个提醒策略。
- 提醒任务:可指定多个接收者(含自己),支持单次与周期性,提醒策略与触达方式同 Todo。
- 通知:一次提醒事件在“某接收者”维度的投递记录,支持站内与 Bark 两种渠道。
- 邀请码:仅邀请码注册,所有用户可生成/管理邀请码。
业务规则与边界条件
- 周期性任务的下一次触发时间
- 使用 用户时区(默认
Asia/Shanghai可配置)。 - 规则类型:
hourly | daily | weekly | monthly | yearly - 计算方式:以“本次 dueAt”为基准,按规则添加时间并做 日历对齐:
hourly:dueAt + n hoursdaily:dueAt + n days(保持时分)weekly:dueAt + n weeks(保持星期与时分)monthly: 若下月无对应日期,则取 该月最后一天 同时分yearly: 若跨闰年导致日期不存在,取 当年同月最后一天 同时分
- 使用 用户时区(默认
- 多提醒策略
- 每个任务可配置多条提前量(如 10 分钟、1 小时)。
- 对每条提前量生成独立触发点:
triggerAt = dueAt - offsetMinutes。
- 浏览器不在线
- 服务端仍生成通知记录(状态
pending/queued/sent)。 - 用户上线后,客户端拉取未读站内通知并展示(通知中心 + 弹窗)。
- 服务端仍生成通知记录(状态
- Bark 推送失败/重试
- 失败进入重试队列(指数退避:1m/5m/15m/1h)。
- 最多重试 5 次,超出后标记
failed。 - 幂等:同一通知记录仅允许一次成功发送。
- 多用户提醒
- 每个接收者创建独立通知记录(便于去重与投递状态追踪)。
- 邀请码策略(默认方案)
- 每个邀请码 可用次数 = 5。
- 有效期 = 7 天,可撤销。
- 邀请码可由任意已注册用户生成与管理。
数据模型(关系型)
核心表
users: 用户invites: 邀请码todos: 个人待办reminder_tasks: 多用户提醒任务recurrence_rules: 周期规则reminder_offsets: 提前提醒策略notifications: 通知实例(按接收者维度)delivery_logs: 投递日志(站内/Bark)
字段示意(详见 schema)
users(id, username, password_hash, timezone, bark_url, created_at)invites(id, code, creator_id, max_uses, used_count, expires_at, revoked_at)todos(id, owner_id, title, description, due_at, recurrence_rule_id)reminder_tasks(id, creator_id, title, due_at, recurrence_rule_id)reminder_task_recipients(task_id, user_id)recurrence_rules(id, type, interval, by_weekday, by_monthday, timezone)reminder_offsets(id, target_type, target_id, offset_minutes, channel_inapp, channel_bark)notifications(id, recipient_id, target_type, target_id, trigger_at, channel, status)delivery_logs(id, notification_id, attempt_no, channel, status, response_meta)
核心接口设计(REST)
认证与邀请码
POST /api/auth/register{ username, password, inviteCode }POST /api/auth/login{ username, password } -> JWTPOST /api/invites创建邀请码GET /api/invites获取邀请码列表POST /api/invites/:id/revoke
Todo
GET /api/todosPOST /api/todosGET /api/todos/:idPUT /api/todos/:idDELETE /api/todos/:id
多用户提醒任务
GET /api/reminder-tasksPOST /api/reminder-tasksGET /api/reminder-tasks/:idPUT /api/reminder-tasks/:idDELETE /api/reminder-tasks/:id
用户与设置
GET /api/users?query=GET /api/mePUT /api/me/settings{ timezone, barkUrl, inappEnabled, barkEnabled }
通知中心
GET /api/notifications?status=unreadPOST /api/notifications/:id/read
Bark 推送设计
调用形式
- 采用 Bark 官方接口:
- GET:
https://bark.server/push/{title}/{body}?group=notify&icon=... - POST: JSON body
{ title, body, group, icon, url, badge, sound }
- GET:
发送内容
title: 任务标题body: 触发时间 + 备注group:notify- 额外参数:
url指向站内通知详情
调度方案(可靠与幂等)
核心思想
- 以 通知表 为唯一投递来源(幂等)。
- 调度器只负责生成通知实例;投递 worker 只发送
pending通知。
通知状态机
pending->queued->sent或failed
触发流程
- 用户创建/更新任务 -> 生成
next_due_at - 生成通知实例:
trigger_at = due_at - offset - Worker 扫描
trigger_at <= now且status = pending,锁定并投递 - 成功则更新
sent,失败则记录failed并按策略重试
关键页面与交互
- 登录/注册(邀请码)
- 注册页要求邀请码与密码确认
- Todo 列表
- 列表 + 新增/编辑弹窗
- 支持单次/周期选择、提前提醒策略
- 提醒任务
- 支持多接收者选择、搜索用户
- 用户列表
- 全部用户可见,支持搜索
- 个人设置
- Bark 链接、站内通知偏好
- 通知中心
- 未读/历史提醒,点击标记已读
工程结构与实现要点
backend/: REST API、调度 worker、Bark 集成frontend/: Next.js UI,响应式布局docker-compose.yml: 数据库与服务
示例伪代码
计算下一次触发
function nextDueAt(dueAt, rule) {
switch (rule.type) {
case "monthly":
return addMonthWithClamp(dueAt, rule.interval);
case "yearly":
return addYearWithClamp(dueAt, rule.interval);
// hourly/daily/weekly...
}
}