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.
5.5 KiB
5.5 KiB
邮件自动预报系统
Next.js 15 + Prisma + MySQL 8 + Ant Design 5 + Worker(IMAP 轮询)。
快速开始
# Windows 一键(推荐 local,不拉 node 镜像)
# .\docs\start-system.ps1
# 或 docs\start-system.cmd
# 全量 compose(需 Docker Hub):.\docs\start-system.ps1 -Mode compose
# 1. 依赖
pnpm install
# 2. 环境
cp .env.example .env
# 本地默认 MySQL 映射 7023(避免与宿主机 3306 冲突)
# DATABASE_URL=mysql://app:app@localhost:7023/email_forecast
# CC_MOCK=true # 无 CC 账号时开 mock
# 3. 数据库
docker compose up -d mysql
pnpm exec prisma db push
pnpm db:seed # 仅账号 admin/ops
# 4. Web + Worker(本地联调推荐;Worker 与系统一起起,才有自动拉取)
pnpm dev:stack
# 等价:pnpm dev 与 pnpm worker 同开
# http://localhost:3100 账号 admin/admin123 或 ops/ops123
# Windows 一键(mysql + web + worker):.\docs\start-system.ps1
# 4b. 仅 Web(不拉 IMAP)
pnpm dev
# 4c. 生产形态三件套(mysql + web + worker)
# 需已有 .env;首次会 db push + seed 账号(SEED_ON_START=true)
pnpm compose:up
pnpm compose:ps # 确认 web/worker/mysql 均为 running
# pnpm compose:logs
# 本机已用 pnpm dev 时,可只补 worker 容器:pnpm compose:up:core
# 5. IMAP 邮箱绑定(推荐:Web 设置页,无需改代码)
# Admin 登录 → 设置 → 新增绑定(填对方邮箱 + QQ 授权码)→ 测试连接
# 兼容回退:仍可在 .env 填 IMAP_USER / IMAP_PASS
pnpm imap:smoke # 仅连通(.env 回退)
pnpm imap:poll # 拉取一轮(优先 DB 绑定)
pnpm worker # 常驻轮询
# Admin 顶栏也可点「立即拉取」
架构
| 进程 | 职责 |
|---|---|
web |
UI + /api/* + ConfirmImport / SaveContainer + 设置/邮箱绑定 |
worker |
仅 IMAP 拉取(读 mailbox_account)+ ParsePipeline + 超时回收 + 补偿 due + retention;禁止调 SaveContainer |
mysql |
业务库 email_forecast |
本地只起
pnpm dev+ mysql 时 不会自动拉信/回收。联调请用pnpm dev:stack、.\docs\start-system.ps1,或docker compose up三件套。
邮件来源
列表数据仅来自 IMAP 拉取(设置页绑定邮箱)。开发种子 / 样例导入 / 旧 Demo 应用已移除。
路由
/login/mails/mails/[id]/mails/[id]/confirm/logs(导入日志 / 拉取记录)/settings(Admin)
测试
docker compose up -d mysql
pnpm exec prisma db push # 含 trace_id 列时需推一次
pnpm test:all # 一条命令:vitest + 覆盖率(coverage/)
pnpm test # 仅 vitest(含 integration,需 MySQL)
pnpm test:e2e # playwright(需先起 dev)
pnpm test:e2e:test-mode # TEST_MODE Playwright(端口 3110)
覆盖率报告:coverage/coverage-summary.json 与终端 text-summary。
TEST_MODE=1 时可用 /test-workbench 注入样例、切故障、看 Mock 请求。
生产告警:配置 ALERT_WEBHOOK_URL 后,IMAP 连续失败 ≥3 或 CC 鉴权/登录失败会 POST JSON(15 分钟去重)。未配置时只写日志。
已知问题与建议
| 项 | 现状 | 建议 |
|---|---|---|
| 关键字未命中 | IGNORED / SKIP_FILTER,不进业务列表 |
属过滤设计;已拉取但分类 UNKNOWN 会以 PARSED 出现在列表供人工处理 |
| IMAP SEARCH/FETCH | 瞬时超时会重试 3 次;鉴权失败不重试(走连续失败退避) | 保持 |
markSeen |
处理失败且尚未落库时不再标已读,便于 lookback 重试 | 已按 UID 入库的仍标已读(DB 幂等) |
| 部分成功(CC 对象 data) | 仍作 TIMEOUT_UNKNOWN 进补偿 |
与「缺 external id」同路径,避免误标成功 |
| 工单/DO/转仓 5xx | 邮件 FAILED,未统一进预报补偿表 |
一键可从详情重试;若要对齐预报补偿可再抽公共队列 |
| 既有单测漂移 | mail-intent / extract-header / four-business / work-order-dedupe 4 项与当前解析文案/字段不一致 |
与本次可观测性无关;建议单独立项对齐 expected |
# CC
pnpm cc:smoke # 跟随 .env(默认 mock 假成功,非 TEST 验收)
pnpm cc:smoke -- --mode=mock # 强制 mock
pnpm cc:smoke -- --mode=live # TEST 真烟雾:需 CC_MOCK=false + CC_USERNAME + 密码
pnpm retention:cleanup # 按 DATA_RETENTION_DAYS 清理(可加 --dry-run)
pnpm retention:cleanup -- --dry-run
CC mock vs live(一期验收)
| 模式 | 条件 | 含义 |
|---|---|---|
| mock | 设置页 Mock 开,或 .env CC_MOCK=true |
SaveContainer/冲突/船司走内存假数据;不算 PRD TEST 烟雾 |
| live | 设置页关 Mock + 用户名/密码(或 .env) |
真打 test.saas...:customerLogin → 冲突/船司/SaveContainer |
配置入口:设置 → CarrierCentral(CC)连接(Admin)。DB 配置优先于 .env,保存后立即生效。
PDF《carriercentral 客户端通用接口》只定义路径与字段;不能替代租户账号。无 customerLogin token 无法 SaveContainer。
顶栏 / GET /api/health 会暴露 cc_mode / cc_live_ready,避免误把 mock 当验收。
文档
- 协作入口(给接手同事):
docs/邮箱项目.md - PRD:
docx/需求规格-邮件自动预报-v0.2.md - 技术设计:
docx/技术设计方案-邮件自动预报-v1.0.md - UI/UX:
docx/产品UI-UX设计方案-邮件自动预报-v1.0.md - 韧性:
docx/异常场景与系统韧性设计.md - 运营 SOP:
docx/运营SOP-邮件自动预报.md