# daybyday **Repository Path**: yimu321/daybyday ## Basic Information - **Project Name**: daybyday - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-10-04 - **Last Updated**: 2026-10-04 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 提醒事项服务平台「记得 / Remindly」 基于 Vue3 + NestJS + PostgreSQL 的提醒事项服务平台:按一次性/纪念日/周期/cron 规则生成触发槽位,由调度 Worker 经幂等日志通过**邮件(SMTP)/ 企业微信机器人 / 钉钉机器人**三渠道发送提醒,支持失败重试、熔断、配额与实时通知(WebSocket)。 ## 目录结构 ``` backend/ NestJS API(src/main.ts)+ 调度 Worker(src/workers/main.ts) frontend/ Vue3 + Vite + Element Plus 单页应用 deploy/ PM2 与 Nginx 部署配置 ``` ## 环境要求 - Node.js >= 20(开发环境 v24) - PostgreSQL >= 15(本地可用 Docker) - 生产环境:PM2、Nginx ## 本地启动 ```powershell # 1. 启动数据库(一次性) docker run -d --name remindly-pg -e POSTGRES_USER=remindly -e POSTGRES_PASSWORD=remindly ` -e POSTGRES_DB=remindly -p 5432:5432 -v remindly-pgdata:/var/lib/postgresql/data postgres:16 # 2. 后端 cd backend npm install copy .env.example .env # 按需修改 DATABASE_URL / JWT / SMTP npx prisma migrate dev # 建表 npm run build npm run start:dev # API :3000(开发热重载) npm run start:worker:dev # 调度 Worker(另开终端) # 3. 前端 cd frontend npm install npm run dev # Vite :5173,/api/v1 代理到 :3000 ``` ## 测试 ```powershell cd backend npm run test # vitest(规则引擎边界用例 + 加解密) npm run build # 类型检查 cd ../frontend npm run build # 前端构建 ``` ## PM2 部署(生产) 完整部署指南见 **[deploy/DEPLOY.md](deploy/DEPLOY.md)**(含目录结构、首次部署、日常运维、排查表)。以下是速查。 ```bash # 0. 一次性:初始化 Git 仓库(本地开发机) bash deploy/init-git.sh # 预演,确认将入库的文件 bash deploy/init-git.sh --apply # 真正执行:建 main/release 分支 # 1. 一次性:服务器初始化(装依赖、建库、配自启) sudo bash deploy/bootstrap.sh # 2. 手工创建 backend/.env(不入库),至少改 DATABASE_URL / # JWT_ACCESS_SECRET / JWT_REFRESH_SECRET / ENCRYPTION_KEY # 3. 首次发布 sudo -u remindly bash deploy/deploy.sh --first # 4. 日常发版(一条命令:git pull → 备份 → 迁移 → 构建 → 重启 → 健康检查) sudo -u remindly bash deploy/deploy.sh # 5. Nginx + HTTPS sudo cp deploy/nginx.conf /etc/nginx/conf.d/remindly.conf sudo sed -i 's/remindly\.example\.com/你的域名/g' /etc/nginx/conf.d/remindly.conf sudo nginx -t && sudo systemctl reload nginx sudo certbot --nginx -d 你的域名 ``` 发布脚本的三个安全阀: 1. **迁移前强制 `pg_dump`**,备份失败即中止发布(迁移不可逆)。 2. **同步产物前校验 `index.html` 存在**,防止空目录上线导致白屏。 3. **健康检查走直连 3000端口**(绕过 Nginx,避免把网关故障误判为应用故障),失败自动回滚代码并二次检查。 常用变体: ```bash bash deploy/deploy.sh --no-frontend # 只改后端时跳过前端构建 bash deploy/deploy.sh --rollback # 回滚到最近一个 tag BRANCH=release bash deploy/deploy.sh # 从 release 分支发布 ``` ### PM2 常用命令 ```bash pm2 start deploy/ecosystem.config.js# 首次启动 pm2 reload deploy/ecosystem.config.js --update-env # 重启(fork 单实例下≈restart) pm2 ls # 状态 pm2 logs remindly-api --lines 100 # API 日志 pm2 logs remindly-worker # Worker 日志 pm2 monit # 资源实时监控 pm2 save && pm2 startup # 开机自启 pm2 install pm2-logrotate # 日志轮转 ``` > **Worker 必须保持单实例 fork。** 它每分钟 tick 认领到期槽位,多实例会导致重试节奏、熔断计数、每日配额全部失真。理由写在 `deploy/ecosystem.config.js` 的注释里,改之前先读。 ## 关键环境变量(backend/.env) | 变量 | 说明 | | --- | --- | | `DATABASE_URL` | PostgreSQL 连接串 | | `JWT_ACCESS_SECRET` / `JWT_REFRESH_SECRET` | 双令牌签名密钥(生产必须更换) | | `JWT_ACCESS_TTL` / `JWT_REFRESH_TTL_DAYS` | 访问令牌 2h / 刷新令牌 30 天 | | `ENCRYPTION_KEY` | 渠道配置 AES-256-GCM 密钥(64 hex) | | `SMTP_HOST/PORT/SECURE/USER/PASS/FROM` | 默认邮件渠道 | | `PUBLIC_BASE_URL` | 前端地址(用于消息内链接与 CORS) | | `TICK_INTERVAL` | Worker 扫描 cron,默认 `* * * * *` | | `QUOTA_DAILY_SENDS` | 每日发送上限,默认 100 | | `FIRE_WINDOW_DAYS` | 槽位预告窗口,默认 90 天 | ## API 概览(统一响应 `{ code, message, data }`) - `POST /api/v1/auth/register|login|refresh|logout|logout-all`、`GET|PATCH /auth/me`、`DELETE /api/v1/users/me` - `GET|POST /reminders`、`GET|PUT|DELETE /reminders/:id`、`POST /reminders/:id/pause|resume|complete`、`POST /reminders/preview-cron` - `GET|POST /channels`、`PUT|DELETE /channels/:id`、`POST /channels/:id/test|default`、`GET /channels/:id/verify` - `GET /notifications`、`GET /notifications/stats`、`POST /notifications/:id/retry` - `GET /export?type=json|csv`、`GET /health`(公开)、`POST /events`(前端埋点);WebSocket 走默认 `/socket.io`(`auth: { token }`) 错误码:`40001/40002` 参数与 cron、`40101/40102` 认证、`40201` 配额、`40301` 权限、`40401` 不存在、`40901` 冲突、`42901` 限流、`50001` 服务端。 ## 调度与可靠性设计 1. `reminder_fire_slots` 为唯一事实来源(主提醒 + 提前预告槽位),创建/修改/恢复时由规则引擎重算。 2. Worker 每分钟 tick:`FOR UPDATE SKIP LOCKED` 认领到期槽位 → 按渠道生成 `notification_logs`(幂等键 `slotId|channelType`,唯一约束兜底)。 3. 发送失败分类:瞬时错误按 1/5/30/120 分钟退避重试 4 次;永久失败立即落 `failed`;渠道连续 10 次瞬时失败熔断 30 分钟。 4. 进程崩溃卡死恢复:`processing/sending` 超 10 分钟自动回收重发。 5. 每日 03:30 清理 180 天前通知日志与槽位、30 天前注销用户匿名化。