167 lines
8.2 KiB
Markdown
167 lines
8.2 KiB
Markdown
# 取名小程序产品规格说明(NamingAssistant)
|
||
|
||
## 1. 文档信息
|
||
- **版本**:v0.1(初版)
|
||
- **创建日期**:2025-11-04
|
||
- **适用范围**:`MiniProgram/NamingAssistant` 首个迭代(姓名生成与收藏)
|
||
- **维护人**:前端负责人、后端接口负责人、测试负责人共用
|
||
|
||
## 2. 背景与目标
|
||
- 提供面向抖音生态的姓名生成服务,支持根据用户输入的姓氏、性别、出生日期与名字长度快速获取候选姓名。
|
||
- 通过广告激励实现变现,确保用户在观看广告后获得生成结果。
|
||
- 支撑用户在本地收藏心仪姓名,限制每日请求频率防止滥用。
|
||
|
||
## 3. 名词与角色
|
||
- **用户**:使用抖音小程序的终端访客。
|
||
- **AI 命名服务**:后端聚合接口,根据提示词返回 5 个姓名及释义。
|
||
- **校验服务**:后端接口,校验姓氏是否合法。
|
||
- **激励广告**:抖音小程序提供的激励视频广告组件。
|
||
|
||
## 4. 产品范围
|
||
- **In Scope**
|
||
- 主页表单输入、校验与广告流程。
|
||
- 结果页展示 5 个姓名与释义,支持收藏。
|
||
- 收藏页展示本地收藏记录、删除、查看详情。
|
||
- 本地记录每日调用次数,超过 10 次给出提示,次数可在后台配置。
|
||
- **Out of Scope**
|
||
- 账户登录、云端收藏同步。
|
||
- 历史生成记录、多端同步。
|
||
- 自定义广告策略与多渠道投放。
|
||
|
||
## 5. 用户流程(KISS)
|
||
1. 用户打开主页填写表单:姓 → 性别 → 出生日期/时间 → 名字字数。
|
||
2. 姓输入失焦触发校验接口;非法返回后提示并清空输入。
|
||
3. 用户点击“生成姓名”,系统执行整体验证;失败则提示错误并阻止提交。
|
||
4. 校验通过后展示激励广告;广告播放完成触发生成逻辑。
|
||
5. 调用生成接口并显示“计算中”加载状态;成功后缓存结果并跳转结果页。
|
||
6. 结果页展示 5 条姓名及含义,用户可选择任意一个收藏,收藏立即写入本地,数量可在后台配置。
|
||
7. 用户可从结果页或主导航进入收藏页查看或删除收藏项。
|
||
|
||
## 6. 页面结构与职责(SOLID)
|
||
- **主页(`pages/home/index`)**
|
||
- 负责表单输入组件渲染与状态管理。
|
||
- 调用校验服务、触发广告播放与生成流程。
|
||
- 控制每日次数提示、跳转结果页。
|
||
- **结果页(`pages/result/index`)**
|
||
- 展示当前生成结果,处理收藏交互。
|
||
- 支持返回主页重新生成。
|
||
- **收藏页(`pages/favorites/index`)**
|
||
- 读取本地收藏列表并渲染。
|
||
- 提供单项删除与查看释义。
|
||
|
||
> 页面逻辑使用独立 `store`(如 `store/namingStore.ts`)管理:当前表单、生成结果、调用次数、收藏集合,避免重复状态(DRY)。
|
||
|
||
## 7. 数据模型(YAGNI:仅覆盖本迭代必要字段)
|
||
| 实体 | 字段 | 类型 | 说明 |
|
||
| --- | --- | --- | --- |
|
||
| `NamingForm` | `surname` | string | 1-2 个汉字,必填 |
|
||
| | `gender` | `'male' \| 'female'` | 单选,必填 |
|
||
| | `birthDate` | `string` | `YYYY-MM-DD`,默认当天,必填 |
|
||
| | `birthTime` | `string \| null` | `HH:mm`,默认空,选填 |
|
||
| | `nameLength` | `'single' \| 'double'` | 单名 or 双名,默认 `double` |
|
||
| `NamingResult` | `name` | string | 生成姓名 |
|
||
| | `meaning` | string | 含义说明 |
|
||
| | `score` | number? | 预留;本迭代不返回(保持可选,默认不展示) |
|
||
| `FavoriteItem` | `id` | string | `name + timestamp` 生成的唯一键 |
|
||
| | `name` | string | 收藏姓名 |
|
||
| | `meaning` | string | 对应释义 |
|
||
| | `createdAt` | string | ISO 时间戳 |
|
||
|
||
## 8. 业务规则
|
||
- 姓氏校验:输入长度 1-2,失焦时调用 `/validate-surname`,返回 `isValid=false` 时清空并 Toast“请输入合法姓氏”。
|
||
- 表单必填项:姓氏、性别、出生日期、名字字数;出生时间选填(为空不纳入提示词)。
|
||
- 提交前整体验证:若任一必填缺失或校验失败,阻止广告播放并给出错误提示。
|
||
- 激励广告完成事件 `onClose` 返回 `isEnded=true` 才允许调用生成接口;否则提示“观看完整广告后才能生成姓名”。
|
||
- 每日次数:基于本地缓存键 `naming:quota:YYYYMMDD` 记录已用次数;达到 10 次时 Toast“今日生成次数已用尽,请明日再试”。
|
||
- 收藏:每个姓名可多次生成;收藏时如同名存在则更新 `createdAt`,避免重复条目。
|
||
- 删除收藏:从本地存储移除对应 `id` 并刷新列表。
|
||
|
||
## 9. 接口契约(接口分离,依赖抽象而非具体实现)
|
||
- **POST `/api/naming/validate-surname`**
|
||
- 请求:`{ "surname": "李" }`
|
||
- 响应:`{ "isValid": true, "message": "" }`
|
||
- 错误码:`40001` 非法字符、`50000` 系统异常。
|
||
- **POST `/api/naming/generate`**
|
||
- 请求:
|
||
```json
|
||
{
|
||
"surname": "李",
|
||
"gender": "male",
|
||
"birthDate": "2025-11-04",
|
||
"birthTime": "",
|
||
"nameLength": "double"
|
||
}
|
||
```
|
||
- 服务端将上述信息组合成提示词,例如:`"以“李”为姓,男孩,出生于2025年11月4日,生成双名,提供5个寓意美好的中文名字"`。
|
||
- 响应:
|
||
```json
|
||
{
|
||
"results": [
|
||
{ "name": "李承泽", "meaning": "承载福泽,寓意富足" },
|
||
{ "name": "李昱辰", "meaning": "昱意为光辉,辰代表时光" },
|
||
{ "name": "李颢宇", "meaning": "广阔天空,胸怀大志" },
|
||
{ "name": "李景曜", "meaning": "景象辉煌,曜为光耀" },
|
||
{ "name": "李辰逸", "meaning": "自在悠然,辰意指时光" }
|
||
]
|
||
}
|
||
```
|
||
- 异常:
|
||
- `42900` 请求超限(由后端或网关返回,与前端本地控制互补)。
|
||
- `50000` 系统异常。
|
||
|
||
## 10. 本地存储策略
|
||
- `tt.setStorageSync('naming:quota:YYYYMMDD', number)`:记录当日已使用次数。
|
||
- `tt.setStorageSync('naming:favorites', FavoriteItem[])`:存储收藏列表。
|
||
- 加载收藏页时若数据缺失则返回空数组,避免抛错。
|
||
|
||
## 11. 激励广告模块
|
||
- 封装 `utils/adService.ts` 暴露 `showRewardedVideoAd(): Promise<void>`。
|
||
- 广告位 ID 通过配置注入,方便后续替换;模块负责加载、展示、清理事件监听。
|
||
- 页面调用时捕获异常并提示“广告加载失败,请稍后重试”。
|
||
|
||
## 12. 错误与提示文案(DRY:集中在 `constants/messages.ts`)
|
||
- `INVALID_SURNAME`:`请输入合法姓氏`
|
||
- `FORM_INCOMPLETE`:`请完整填写必填项`
|
||
- `WATCH_AD_TO_CONTINUE`:`观看完整广告后才能生成姓名`
|
||
- `QUOTA_EXCEEDED`:`今日生成次数已用尽,请明日再试`
|
||
- `GENERATION_FAILED`:`生成失败,请稍后再试`
|
||
|
||
## 13. 验收标准(测试覆盖)
|
||
- **表单校验**:
|
||
- 输入非法姓氏提示并清空。
|
||
- 必填项缺失无法触发广告。
|
||
- **广告流程**:
|
||
- 未完整观看广告不可调用生成接口。
|
||
- 广告失败异常提示正常。
|
||
- **生成结果**:
|
||
- 成功返回后跳转结果页,展示 5 条记录及释义。
|
||
- “计算中” loading 在接口完成后消失。
|
||
- **收藏功能**:
|
||
- 收藏后收藏页可见,删除后立即消失。
|
||
- 重复收藏刷新时间戳不新增条目。
|
||
- **请求限额**:
|
||
- 连续触发 10 次后出现限额提示,第 11 次被阻止。
|
||
|
||
## 14. 非功能需求
|
||
- Loading 状态 300ms 内出现,避免空白。
|
||
- API 网络失败时 2s 内给出提示。
|
||
- 本地存储读写失败需兜底为内存态并告警(日志)。
|
||
|
||
## 15. 依赖与配置
|
||
- 抖音小程序基础库 ≥ 3.0;需启用激励视频广告能力。
|
||
- 后端提供校验与生成接口;约定响应时间 ≤ 3s。
|
||
- 配置文件 `config/index.ts`:广告位 ID、接口基础地址、最大生成次数。
|
||
|
||
## 16. 待确认事项
|
||
- 广告必须观看时长是否有具体数值要求(默认以 `isEnded` 判断)。
|
||
- AI 接口返回释义字段是否稳定,若缺失由兜底。
|
||
- 是否需要埋点统计广告完成率与收藏次数(暂未纳入:YAGNI)。
|
||
|
||
## 17. 里程碑
|
||
- **M1**:完成项目脚手架、页面路由与表单控件。
|
||
- **M2**:接入校验与生成接口,贯通广告流程。
|
||
- **M3**:实现收藏、本地限额逻辑并完成联调、测试用例。
|
||
|
||
> 设计遵循 KISS(简洁流程)、DRY(统一状态与文案)、YAGNI(仅落地当前需求),页面与服务模块职责清晰满足 SOLID。
|
||
|