# Peeka · 半熟人匿名约会邀请函

> **产品定位**：帮助刚加微信的半熟人，用轻松、低压力的匿名方式发起第一次线下约会，拉进社交距离。  
> **平台**：微信小程序  
> **目标用户**：16–30 岁  
> **版本**：V1.6 PRD（含 V1.3–V1.6 原型迭代）  
> **日期**：2026-06-07  
> **最近更新**：2026-06-07

---

## 1. 背景与问题

| 现状 | 痛点 |
|------|------|
| 刚加微信，聊了几句 | 直接约见面压力大，怕尴尬、怕被拒绝 |
| 想进一步了解对方 | 不知道对方喜好，不知道约什么、什么时候 |
| 微信好友关系已建立 | 但身份完全透明，缺少「试探性」的安全距离 |

**产品价值**：用「匿名邀请函 + 分步确认」降低心理门槛，让双方在有默契后再揭晓身份。

---

## 2. 产品目标

### 2.1 核心目标
- 邀请人可在 **不暴露微信昵称/头像/账号** 的前提下，向指定微信好友发送约会邀请函
- 被邀请人按 **同意 → 约会类型 → 时间段 → 见面地点** 完成响应
- 双方确认后，邀请人可查看完整约会信息并 **二次确认时间**，再通知被邀请人

### 2.2 成功指标（V1）
| 指标 | 目标 |
|------|------|
| 邀请函发送成功率 | ≥ 95% |
| 被邀请人打开率 | ≥ 60% |
| 完整走完流程率（同意→填完地点） | ≥ 40% |
| 邀请人最终确认率 | ≥ 70% |

---

## 3. 用户角色

| 角色 | 定义 | 核心行为 |
|------|------|----------|
| **邀请人** | 发起约会邀请的微信用户 | 编辑身份提示、制作邀请函、匿名发送、确认约会 |
| **被邀请人** | 收到邀请函的微信好友 | 查看匿名邀请、分步响应、填写地点 |
| **系统** | 小程序后台 | 校验好友关系、管理匿名态、推送状态变更 |

---

## 4. 核心业务规则

### 4.1 好友关系校验（规则 1）
- 仅可向 **当前微信好友** 发送邀请函
- 发送前调用微信开放能力校验好友关系（`wx.getFriendList` 或服务端 openid 映射校验）
- 非好友：提示「请先添加对方为微信好友」

### 4.2 匿名机制（规则 2）
| 阶段 | 邀请人可见信息 | 被邀请人可见信息 |
|------|----------------|------------------|
| 发送前 ~ 被邀请人点击「同意」前 | 自己完整信息 | 仅：身份提示 + 邀请函内容 + 城市定位 |
| 被邀请人同意后 ~ 邀请人确认前 | 被邀请人填写的约会信息（类型/时间/地点），**仍不显示**被邀请人微信信息 | 仍不显示邀请人微信信息 |
| 邀请人点击「确认约会」后 | 双方微信昵称、头像（可选）互相可见 | 同上 |

**身份提示**（邀请人预设，可多选/自定义）示例：
- **基础标签**（多选）：同城、爱好、认识渠道等
- **身份线索**（选填，最多 6 条）：上次见面时间、共同话题、共同好友数、喜好歌手、家乡、毕业学校等
- **自定义短句**（≤ 30 字）：如「通过朋友认识~」
- 被邀请人在 P06 同意页可预览上述组合信息，但 **看不到邀请人微信昵称/头像**

**拒绝时的匿名规则（重要）**：
- 被邀请人 **不知道** 邀请人是谁
- 邀请人 **知道** 被邀请人是谁（微信好友关系单向可见）
- 拒绝确认弹窗需明确告知上述逻辑，避免用户误解

### 4.3 邀请函三段式流程（规则 3）

```
被邀请人视角：
  Step 1  确认同意（Yes / No）
  Step 2  选择约会类型
  Step 3  选择约会时间段 + 手动输入见面地点
  Step 4  提交 → 等待邀请人确认

邀请人视角（收到响应后）：
  查看约会详情 → 时间是否合适 → 确认 / 「时间不合适」撰写消息
  → 以消息方式通知被邀请人（可说明原因或建议新时间）

被邀请人可选路径（V1.3+）：
  P06 同意前 → 💬 匿名聊一聊 → 再决定 Yes / No
```

### 4.4 城市定位展示
- 展示 **城市级** 定位（如「上海」），不展示精确地址
- 来源：用户授权 `wx.getLocation` 或手动选择城市
- 用于增强「同城/可见面」信任感

---

## 5. 用户旅程

### 5.1 邀请人旅程

```mermaid
flowchart TD
    A[进入小程序] --> B[完善个人资料/城市]
    B --> C[创建邀请函]
    C --> D[编辑身份提示]
    D --> E[选择邀请函模板/自定义文案]
    E --> F[选择微信好友]
    F --> G{好友校验}
    G -->|失败| H[提示先加好友]
    G -->|成功| I[匿名发送]
    I --> J[等待被邀请人响应]
    J --> K{收到响应}
    K -->|拒绝| L[收到拒绝通知]
    K -->|完成填写| M[查看约会信息]
    M --> N{时间合适?}
    N -->|否| O[撰写消息通知对方]
    N -->|是| P[确认约会]
    P --> Q[双方身份揭晓 + 约会锁定]
```

### 5.2 被邀请人旅程

```mermaid
flowchart TD
    A[收到微信服务通知/分享卡片] --> B[打开邀请函]
    B --> C[查看匿名信息+身份提示]
    C --> C2{先聊一聊?}
    C2 -->|是| C3[匿名聊天 P15b]
    C3 --> D{是否同意?}
    C2 -->|否| D
    D -->|No| E[拒绝 → 通知邀请人]
    D -->|Yes| F[惊喜过渡页 P07 · 无插图]
    F --> G[选择约会类型]
    G --> H[选择日期+时间]
    H --> I[手动输入见面地点]
    I --> J[提交]
    J --> K[等待邀请人确认]
    K --> L{邀请人确认?}
    L -->|确认| M[约会成功 + 身份揭晓]
    L -->|拒绝| N[收到说明 + 可重新协商]
```

---

## 6. 功能模块

### 6.1 模块总览

| 模块 | 优先级 | 说明 |
|------|--------|------|
| M1 用户与授权 | P0 | 微信登录、城市、基础资料 |
| M2 身份提示管理 | P0 | 预设标签 + 自定义 |
| M3 邀请函编辑 | P0 | 模板、文案、配图风格 |
| M4 好友选择与发送 | P0 | 好友列表、匿名发送 |
| M5 被邀请人响应流 | P0 | 四步交互流程 |
| M6 邀请人确认流 | P0 | 查看、确认/拒绝 |
| M7 消息通知 | P0 | 订阅消息 + 服务通知 |
| M8 我的约会 | P0 | 历史记录、四 Tab 状态管理（V1.3） |
| M9 模板商城 | P2 | 更多 meme/风格模板 |
| M10 匿名聊一聊 | P1 | Yes 前双方匿名会话（V1.3） |

---

## 7. 页面清单

| 页面 ID | 页面名称 | 角色 | 说明 |
|---------|----------|------|------|
| P01 | 首页 | 通用 | 发起邀请、💬 聊一聊入口、我的约会、进行中邀请列表 |
| P02 | 身份提示 | 邀请人 | 基础标签 + 身份线索（6 条选填）+ 预览 |
| P03 | 制作邀请函 | 邀请人 | 微信表情选择、中英双语文案编辑、可选约会类型 |
| P04 | 选择好友 | 邀请人 | 微信好友列表、匿名发送 |
| P05 | 发送成功 | 邀请人 | 等待被邀请人响应 |
| P06 | 邀请函-同意页 | 被邀请人 | 💬 先聊再决定；Yes / No；身份提示预览 |
| P07 | 惊喜过渡页 | 被邀请人 | 中英双语情绪爆点，**无插图**；主色粉标题区 |
| P08 | 约会类型选择 | 被邀请人 | 氛围 / 美食 Tab；图标网格单选 |
| P09 | 时间选择 | 被邀请人 | 日历多选 + 时间滚轮 |
| P10 | 地点输入 | 被邀请人 | 手动输入见面地点 |
| P11 | 提交成功 | 被邀请人 | 已提交，等待邀请人确认 |
| P12 | 邀请人-响应详情 | 邀请人 | 查看类型/时间/地点；确认约会 / 时间不合适（发消息） |
| P14 | 约会成功 | 双方 | 随机庆祝 Emoji + 身份揭晓 + 约会详情 + 添加日历 |
| — | 已拒绝 | 被邀请人 | 婉拒后随机安慰语（4 条轮换） |
| P15 | 聊一聊列表 | 通用 | 匿名邀请相关会话汇总 |
| P15b | 匿名聊天室 | 通用 | Yes 前可聊；不展示双方微信昵称 |
| P16 | 约会记录 | 通用 | 四 Tab：已完成 / 进行中 / 已拒绝 / 被拒绝 |

> **说明**：原 P13「确认/拒绝」已合并入 P12；高保真原型见 `prototype/index.html`。

---

## 8. 状态机

### 8.1 邀请函状态

| 状态码 | 状态名 | 触发条件 |
|--------|--------|----------|
| `draft` | 草稿 | 邀请人编辑中 |
| `sent` | 已发送 | 匿名发送成功 |
| `viewed` | 已查看 | 被邀请人打开 |
| `rejected` | 已拒绝 | 被邀请人点 No |
| `accepted_step1` | 已同意 | 被邀请人点 Yes |
| `type_selected` | 已选类型 | 完成 Step 2 |
| `time_selected` | 已选时间 | 完成 Step 3 |
| `location_submitted` | 已提交地点 | 完成 Step 4 |
| `inviter_confirmed` | 邀请人已确认 | 邀请人点确认 |
| `inviter_declined` | 邀请人已拒绝 | 邀请人拒绝时间 |
| `completed` | 约会锁定 | 双方确认完成 |
| `expired` | 已过期 | 超过 7 天未响应 |

---

## 9. 数据模型（核心字段）

### 9.1 用户 User
```
userId, openId, unionId, nickName(加密存储), avatarUrl(加密),
city, identityHints[], createdAt
```

### 9.2 邀请函 Invitation
```
invitationId, inviterId, inviteeId,
wxEmojiId,           // 微信表情 ID（V1.6）
inviteMessageCn,     // 邀请中文案
inviteMessageEn,     // 邀请英文案
allowedDateTypes[],  // 邀请人可选类型（吃饭/运动等）
identityHints[],     // 基础标签
clueAnswers{},       // 身份线索键值（V1.3）
city, status, createdAt, expiredAt
```

### 9.3 约会响应 DateResponse
```
responseId, invitationId,
dateType,          // 约会类型枚举
dateTypeLabel,     // 显示名
selectedDate,      // 日期
selectedTime,      // 时间
meetingLocation,   // 被邀请人输入的地点
submittedAt
```

### 9.4 确认记录 Confirmation
```
confirmationId, invitationId,
inviterAction,     // confirm | decline
declineReason,     // 可选
confirmedAt
```

---

## 10. 约会类型（V1 预设）

### 10.1 氛围类（what's your vibe?）
| ID | 名称 | 图标 |
|----|------|------|
| `walk` | 散步 | 🚶 |
| `movie` | 看电影 | 🎬 |
| `dance` | 跳舞/酒吧 | 💃 |
| `amusement` | 游乐园 | 🎢 |
| `beach` | 户外/海边 | 🏝️ |
| `golf` | 运动 | ⛳ |

### 10.2 美食类（what are we feelin'?）
| ID | 名称 | 图标 |
|----|------|------|
| `burger` | 汉堡快餐 | 🍔 |
| `sushi` | 日料寿司 | 🍣 |
| `ramen` | 面食拉面 | 🍜 |
| `taco` | 墨西哥餐 | 🌮 |
| `pizza` | 披萨 | 🍕 |

> V1 策略：邀请人可在创建时 **限定可选类型集合**（如只开放美食类或氛围类），或开放全部。

---

## 11. 通知策略

| 事件 | 接收方 | 通知方式 | 文案示例 |
|------|--------|----------|----------|
| 邀请函发送 | 被邀请人 | 订阅消息 + 分享卡片 | 「有人想和你约会，快来看看 👀」 |
| 被拒绝 | 邀请人 | 订阅消息 | 「你的邀请没有被接受，下次加油」 |
| 完成填写 | 邀请人 | 订阅消息 | 「对方已选好时间地点，快去确认！」 |
| 邀请人确认 | 被邀请人 | 订阅消息 | 「约会确认啦！周六 6 点见 💖」 |
| 邀请人拒绝时间 | 被邀请人 | 订阅消息 + 应用内消息 | 「时间不太合适，对方留了句话…」 |
| 匿名聊天新消息 | 对方 | 订阅消息（可选） | 「你的匿名邀请有新回复」 |

---

## 12. 边界与异常

| 场景 | 处理 |
|------|------|
| 非微信好友 | 阻断发送，引导加好友 |
| 重复发送（24h 内同一人） | 提示「已发送过邀请，请等待响应」 |
| 邀请函过期（7 天） | 状态置 `expired`，双方不可操作 |
| 被邀请人中途退出 | 保存进度，下次打开继续 |
| 邀请人拒绝时间 | 被邀请人可修改时间重新提交（V1.1） |
| 未成年人 | 注册时确认年满 16 岁 |
| 违规内容 | 地点/文案敏感词过滤 |

---

## 13. 非功能需求

| 类别 | 要求 |
|------|------|
| 性能 | 首屏 < 2s，邀请函打开 < 1.5s |
| 安全 | 匿名期 openid 不向前端暴露给对方 |
| 隐私 | 符合《个人信息保护法》，提供隐私政策 |
| 兼容 | 微信基础库 ≥ 2.25.0，iOS/Android |
| 设计 | 粉彩柔和风 + 中英双语，见 §18 与 `docs/UI设计稿-约会邀请函.md` |
| 文案 | 核心页面中英双语展示，语气轻松有趣（非正式翻译腔） |

---

## 14. V1 范围 / 不做

### ✅ V1 做
- 匿名邀请函完整流程
- 微信表情包邀请函（替代静态 meme 图模板）
- 身份提示：基础标签 + 6 条可选线索
- 邀请人可选约会类型（吃饭 / 运动 / 喝酒 / Citywalk + 自定义）
- 6+5 约会类型（被邀请人响应时选择）
- 日期时间选择器
- 手动输入地点
- 订阅消息通知
- 城市展示
- **V1.3+** 匿名聊一聊（仅邀请相关会话，Yes 前可用）
- **V1.3+** 约会记录四 Tab
- **V1.3+** 邀请人「时间不合适」消息通知（非简单 Toast）
- **V1.3+** 拒绝页随机安慰语

### ❌ V1 不做
- 通用即时聊天 / 非邀请场景 IM
- 支付/订座
- 精确 GPS 导航
- 陌生人匹配（非好友）
- 视频通话
- 多被邀请人/群发

---

## 15. 里程碑

| 阶段 | 周期 | 交付 |
|------|------|------|
| 设计 | 1 周 | PRD + UI 稿 + 交互原型 |
| 开发 | 3 周 | 前后端 + 微信能力接入 |
| 测试 | 1 周 | 全流程 + 边界 case |
| 灰度 | 1 周 | 50 用户内测 |

---

## 16. 风险

| 风险 | 缓解 |
|------|------|
| 微信好友 API 限制 | 提前申请权限，备选分享卡片方案 |
| 匿名被滥用骚扰 | 举报入口 + 频率限制 + 敏感词 |
| 用户爽约 | 确认后展示双方信息，提高沉没成本 |
| 低龄用户安全 | 年龄门槛 + 见面安全提示 |

---

## 17. 版本迭代记录

### V1.3 · 交互增强（2026-06）

| 功能 | 说明 |
|------|------|
| 💬 聊一聊 | 首页左上角 FAB + P06 同意页入口；P15 列表 + P15b 聊天室 |
| 匿名聊天规则 | 双方不展示微信昵称/头像；仅关联当前匿名邀请 |
| P16 约会记录 | 已完成 / 进行中 / 已拒绝 / 被拒绝 四 Tab |
| P12 时间不合适 | 弹窗撰写消息 → 发送后 Toast/通知被邀请人 |
| 拒绝弹窗文案 | 明确「你不知道对方是谁，但对方知道你是谁」 |
| 已拒绝页 | 每次进入随机展示 4 条中英安慰语之一 |

### V1.5 · 粉彩柔和视觉（2026-06）

| Token | 色值 | 用途 |
|-------|------|------|
| Background | `#FFFAF0` | 全局背景 |
| Primary | `#FFC1CC` | 主按钮、选中态、链接、标签描边 |
| Aux Pink | `#F4C2C2` | 次要按钮 |
| Aux Cyan | `#E7FEFF` | 💬 FAB、P03 预览区背景 |
| Aux Cream | `#F0EAD6` | No 按钮、聊天提示条 |
| Text | `#5C5346` / `#9A9088` | 正文 / 辅助说明 |
| Card | 圆角 `24px` | 卡片、选项格、弹窗 |

- 去掉霓虹渐变、强外发光；主按钮为纯色粉 + 深色字
- 按钮点击涟漪动效；P07 背景轻噪点纹理

### V1.6 · 中英双语与信息精简（2026-06）

**文案规范**
- 全站核心文案采用 **双层结构**：中文主句（加粗）+ 英文副句（较小、斜体、粉/灰色）
- 导航栏（P03 / P08 / P09 / P10 等）采用与 P08 同款 **夸张双语标题**
- 主按钮支持双层文案（如「发起约会邀请 / Send an anonymous invite ✨」）
- 语气要求：有趣、轻松、略带 meme 感，避免生硬直译

**页面级调整**

| 页面 | 变更 |
|------|------|
| P01 | 去掉首页 Slogan 标语块；保留 Logo、城市、主 CTA、进行中列表双语 |
| P03 | 表情网格 **仅显示 Emoji**，去掉格内中文名；预览区 **去掉 `[表情名]`**；预览区底 `#E7FEFF`；约会类型 Chip 中英双层 |
| P06 | 去掉表情下方 `[表情名]`；Yes 按钮双层文案 |
| P07 | **移除顶部插图**；标题区改主色粉 `#FFC1CC`；卡片内中英双语 |
| P08 | 导航双层标题；氛围/美食 Tab 双层（如「氛围 / Vibe ✨」） |
| P09 / P10 | 导航双层标题（如「哪天有空？！📅 / When are you free?」） |
| P14 | 顶部庆祝 Emoji 区改 **白色卡片**（与下方信息卡一致）；**去掉 `[表情名]`**；每次进入 **随机庆祝 Emoji**；标题改为中性「逮到你了！/ I got you!!」（去掉 gendered 用词） |

---

## 18. 交互与组件规范（原型对齐）

高保真原型：`prototype/`（V1.6）

| 组件 | 规范 |
|------|------|
| 主按钮 `btn-primary` | 粉底 `#FFC1CC`，深色字，胶囊形，可双层文案 |
| 次要按钮 | `#F4C2C2` 填充；No 用 `#F0EAD6`；💬 FAB 用 `#E7FEFF` |
| 标签/Chip 未选中 | 白底 + 粉描边；选中：粉底 + 深色字 |
| 输入框 | 胶囊形，聚焦淡粉光晕 |
| P08 选项格选中 | 轻微放大 + 淡粉径向光晕 |
| 卡片 | 白底、`24px` 圆角、`1px` 半透明描边、柔和阴影 |

**微信表情邀请函（P03）**
- 10 个预设微信风格 Emoji，选中后同步更新 P06 预览文案（中/英可编辑）
- 预览卡片：上方 `#E7FEFF` 表情区 + 下方可编辑中英邀请语

**匿名聊天（P15/P15b）**
- 入口：P01 左上角、P06 顶部
- 气泡：己方粉底，对方白底描边
- 顶部提示：「匿名模式 · 不展示微信昵称」

---

## 19. 数据模型补充（V1.3+）

### 19.1 匿名会话 ChatSession
```
sessionId, invitationId, participants[], lastMessageAt, unreadCount
```

### 19.2 聊天消息 ChatMessage
```
messageId, sessionId, senderRole,  // inviter | invitee
content, sentAt, isRead
```

### 19.3 约会记录（列表视图）
```
invitationId, statusTab,  // completed | ongoing | declined | rejected
title, subtitle, statusLabel, updatedAt
```

---

*文档维护：产品组 · Peeka*
