feat: realistic face avatar + voice input + ASR endpoint
This commit is contained in:
@@ -0,0 +1,253 @@
|
||||
# 分享功能设计方案
|
||||
|
||||
## 1. 概述
|
||||
|
||||
**目标**:用户可通过分享面试/简历等给好友或微信群,每次有效分享获得积分奖励,积分可抵扣面试/简历优化次数,形成用户增长闭环。
|
||||
|
||||
**核心逻辑**:分享者 A → 生成分享链接 → 非 A 的其他用户点击 → 计入有效分享一次 → A 获得 1 个「分享积分」,每 3 次有效分享可兑换 1 次面试或简历优化次数。
|
||||
|
||||
---
|
||||
|
||||
## 2. 数据模型
|
||||
|
||||
### User 新增字段
|
||||
|
||||
```
|
||||
shareCredits: number // 分享积分,默认 0
|
||||
```
|
||||
|
||||
- 1 个 shareCredit 可兑换 1 次 面试 或 1 次 简历优化
|
||||
- 在 QuotaService 中作为兜底:当 interviewCredits / resumeOptimizeCredits 为 0 时尝试消耗 shareCredits
|
||||
|
||||
### ShareRecord 集合
|
||||
|
||||
```
|
||||
@Schema({ timestamps: true })
|
||||
ShareRecord {
|
||||
_id: ObjectId
|
||||
userId: ObjectId // 分享者
|
||||
shareCode: string // 8位唯一短码 (hex),用于分享链接
|
||||
type: 'interview' | 'resume' | 'app'
|
||||
refId: string // 关联的面试/简历ID(可选)
|
||||
title: string // 分享标题
|
||||
description: string // 分享描述
|
||||
visitCount: number // 总访问次数
|
||||
creditedCount: number // 已计为有效的访问次数
|
||||
isActive: boolean // 链接是否有效
|
||||
createdAt: Date // timestamps
|
||||
updatedAt: Date
|
||||
}
|
||||
|
||||
index: { shareCode: 1 } unique
|
||||
index: { userId: 1, createdAt: -1 }
|
||||
```
|
||||
|
||||
### ShareVisit 集合(访问记录)
|
||||
|
||||
```
|
||||
@Schema({ timestamps: true })
|
||||
ShareVisit {
|
||||
_id: ObjectId
|
||||
shareId: ObjectId // 关联的 ShareRecord
|
||||
sharerId: ObjectId // 分享者 userId(冗余,便于查询)
|
||||
visitorId: string // 访问者标识(openId 或 匿名ID)
|
||||
visitorUserId: ObjectId // 访问者 userId(如果已注册/登录)
|
||||
credited: boolean // 是否已为此访问发积分
|
||||
creditedAt: Date
|
||||
createdAt: Date // timestamps
|
||||
}
|
||||
|
||||
index: { shareId: 1, visitorId: 1 } unique // 同一人只计一次
|
||||
index: { sharerId: 1, createdAt: -1 }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. API 设计
|
||||
|
||||
| 方法 | 路径 | 权限 | 说明 |
|
||||
|------|------|------|------|
|
||||
| POST | /api/share/create | JWT | 生成分享链接,返回 shareCode + URL |
|
||||
| GET | /api/share/visit/:shareCode | Public | 访问分享链接,记录访问+判定发放积分 |
|
||||
| GET | /api/share/stats | JWT | 获取我的分享统计(总分享次数、总积分、今日积分) |
|
||||
| GET | /api/share/records | JWT | 获取我的分享记录列表(分页) |
|
||||
| GET | /api/share/visitors | JWT | 获取访问过我分享的用户列表(分页) |
|
||||
|
||||
### POST /api/share/create
|
||||
|
||||
Request:
|
||||
```json
|
||||
{
|
||||
"type": "interview" | "resume" | "app",
|
||||
"refId": "xxx",
|
||||
"title": "我在职引完成了AI模拟面试",
|
||||
"description": "快来和我一起练习面试吧"
|
||||
}
|
||||
```
|
||||
|
||||
Response:
|
||||
```json
|
||||
{
|
||||
"shareCode": "a1b2c3d4",
|
||||
"shareUrl": "https://zhiyin.app/share/a1b2c3d4",
|
||||
"wechatShareInfo": {
|
||||
"title": "...",
|
||||
"description": "...",
|
||||
"path": "/pages/share/share?code=a1b2c3d4"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### GET /api/share/visit/:shareCode
|
||||
|
||||
- 如果来自微信小程序:记录 `visitorId = openId`
|
||||
- 如果来自 H5 链接:记录 `visitorId = 匿名设备ID`(可选)
|
||||
- 判定条件:
|
||||
- `visitorId !== sharer.openId`(自己点自己不算)
|
||||
- 该 `visitorId` 之前未在该 shareId 下领过积分
|
||||
- 当日该分享者已获得积分 < 3(日上限)
|
||||
- 满足条件 → `credited = true`,shareCredits + 1
|
||||
- 返回重定向或展示落地页
|
||||
|
||||
### GET /api/share/stats
|
||||
|
||||
```json
|
||||
{
|
||||
"totalShares": 15,
|
||||
"totalVisits": 43,
|
||||
"creditedCount": 12,
|
||||
"todayCredited": 2,
|
||||
"shareCredits": 4
|
||||
}
|
||||
```
|
||||
|
||||
### GET /api/share/records
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"shareCode": "a1b2c3d4",
|
||||
"type": "interview",
|
||||
"title": "我在职引完成了AI模拟面试",
|
||||
"visitCount": 5,
|
||||
"creditedCount": 3,
|
||||
"createdAt": "2026-06-12T10:00:00Z"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
### GET /api/share/visitors
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"visitor": { "nickname": "张三", "avatar": "..." },
|
||||
"credited": true,
|
||||
"creditedAt": "2026-06-12T10:30:00Z"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. 积分兜底机制
|
||||
|
||||
在 `QuotaService.checkAndDeductInterview()` 和 `checkAndDeductOptimize()` 中增加兜底:
|
||||
|
||||
```
|
||||
if (interviewCredits <= 0 && shareCredits > 0) {
|
||||
shareCredits -= 1
|
||||
return // 用分享积分抵扣
|
||||
}
|
||||
```
|
||||
|
||||
同时新增 `useShareCredit(userId, type)` 方法由前端显式调用,或自动在抵扣链中完成。
|
||||
|
||||
---
|
||||
|
||||
## 5. 前端实现
|
||||
|
||||
### 5.1 分享入口
|
||||
|
||||
**进入点 1:面试报告页**(`pages/report/report.vue`)
|
||||
- 在"生成分享卡片"按钮旁增加"分享给好友"按钮
|
||||
- 点击后调用 `POST /api/share/create` 生成 shareCode
|
||||
- 微信小程序内直接调 `wx.shareAppMessage`
|
||||
- H5 环境复制分享链接到剪贴板
|
||||
|
||||
**进入点 2:简历优化结果页**(`pages/result/result.vue`)
|
||||
- 同上
|
||||
|
||||
**进入点 3:应用首页**(`pages/index/index.vue`)
|
||||
- "邀请好友"入口,固定分享 app 类型
|
||||
|
||||
### 5.2 我的分享页
|
||||
|
||||
**页面位置**:`/pages/share/share.vue`
|
||||
**进入方式**:用户「我的」页面 → "我的分享" 菜单项
|
||||
|
||||
页面内容:
|
||||
- 顶部统计卡片:总收益积分、今日收益、总分享次数
|
||||
- "分享给好友"主按钮
|
||||
- Tab 切换:「分享记录」/ 「访问记录」
|
||||
- 分享记录列表:分享类型、标题、访问数、有效数、时间
|
||||
- 访问记录列表:访客昵称、访问时间、是否已积分
|
||||
|
||||
### 5.3 微信分享
|
||||
|
||||
使用 uni-app `onShareAppMessage` 生命周期:
|
||||
```javascript
|
||||
// 在页面中定义
|
||||
onShareAppMessage() {
|
||||
return {
|
||||
title: '我在职引完成了AI模拟面试',
|
||||
path: `/pages/share/share?code=${this.shareCode}`,
|
||||
imageUrl: '...'
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 5.4 H5 分享链接
|
||||
|
||||
分享链接格式:`https://zhiyin.app/share/{shareCode}`
|
||||
H5 落地页展示:
|
||||
- 分享者信息
|
||||
- 分享内容预览
|
||||
- "打开小程序" / "下载 App" 引导按钮
|
||||
|
||||
---
|
||||
|
||||
## 6. 风控规则
|
||||
|
||||
| 规则 | 说明 |
|
||||
|------|------|
|
||||
| 日上限 | 同一用户每日最多获 3 个分享积分 |
|
||||
| 自分享过滤 | 自己点自己的链接不计数 |
|
||||
| 同人去重 | 同一访客对同一链接只计一次 |
|
||||
| 链接有效期 | 分享链接 30 天有效期 |
|
||||
| 频率限制 | 每分钟最多创建 5 次分享(前端控制) |
|
||||
|
||||
---
|
||||
|
||||
## 7. 存储方案
|
||||
|
||||
- **ShareRecord**:MongoDB 集合 `sharerecords`
|
||||
- **ShareVisit**:MongoDB 集合 `sharevisits`
|
||||
- 积分字段 `shareCredits` 存储在 User 文档上,`$inc` 原子操作确保并发安全
|
||||
|
||||
---
|
||||
|
||||
## 8. 依赖模块
|
||||
|
||||
- `QuotaService`(来自 UserModule)- 积分发放与抵扣
|
||||
- `UserModule`(获取 User 信息、校验身份)
|
||||
- `PricingModule`(@Global 已有,无需额外导入)
|
||||
|
||||
---
|
||||
|
||||
## 9. 未纳入 MVP 的内容
|
||||
|
||||
- 分享链接落地页(H5 路由 `/share/:code`)— 第一期直接返回 JSON
|
||||
- 分享数据可视化图表
|
||||
- 积分兑换商城
|
||||
- 排行榜 / 邀请竞赛
|
||||
Reference in New Issue
Block a user