Files
zhiyin/docs/PAYMENT-REDESIGN.md

9.8 KiB
Raw Permalink Blame History

产品改造方案:付费体系重构 + 数字人面试

2026-06-11 · v1.0

概述

将现有一刀切的 remaining 免费额度模式,改为按产品线独立计费 + 会员套餐含额度 + 数据库配置化的灵活付费体系。

数据库模型变更

User Schema 新增字段

字段 类型 默认值 说明
interviewCredits number 1 AI 数字人面试可用次数(含首次免费)
resumeOptimizeCredits number 0 简历优化可用次数
resumeDownloadCredits number 0 简历下载可用次数
freeOptimizeUsed number 0 已使用免费优化次数(上限 3

旧的 remaining 字段保留,仅限老用户兼容,新逻辑不再使用。

Resume Schema 新增字段

字段 类型 默认值 说明
version number 1 版本号,每次 AI 改写 +1
contentHash string '' 内容 MD5,用于判断是否改版
paidDownload boolean false 是否已购买该版本的下载权

contentHash 在 create 和 optimize 后自动更新。

PaymentOrder Schema 新增字段

字段 类型 默认值 说明
type string 'membership' membership / interview / optimize / download
metadata Mixed {} 产品粒度信息(如 { resumeId, version }

定价配置(SiteConfig key=pricing

单一配置源,所有定价和套餐内容后台可编辑:

{
  "interview": {
    "firstFree": true,
    "pricePerSession": 500,
    "creditsPerPurchase": 1
  },
  "resumeOptimize": {
    "freeLimit": 3,
    "pricePerOptimize": 300,
    "creditsPerPurchase": 1
  },
  "resumeDownload": {
    "pricePerDownload": 200,
    "creditsPerPurchase": 1
  },
  "plans": {
    "growth": {
      "price": 1990,
      "durationDays": 30,
      "credits": {
        "interview": 999,
        "resumeOptimize": 20,
        "resumeDownload": 10
      },
      "features": [
        "免费版全部权益",
        "AI 数字人面试无限次",
        "详细面试报告(四维评分)",
        "进步轨迹雷达图 + 打卡",
        "每日一题推送",
        "参考回答思路",
        "公司真题库"
      ]
    },
    "sprint": {
      "price": 4990,
      "durationDays": 30,
      "credits": {
        "interview": 999,
        "resumeOptimize": 50,
        "resumeDownload": 30
      },
      "features": [
        "成长版全部权益",
        "AI 语音分析(语气词/语速检测)",
        "技能缺口分析报告",
        "学习路径推荐",
        "真人导师 1v1 点评(每月 1 次)",
        "简历精修(每月 1 次)",
        "内推优先"
      ]
    }
  }
}

配额检查逻辑

所有配额检查收敛到统一的 QuotaGuardQuotaService,不再散落在各处。

// 配额服务
class QuotaService {
  checkInterview(user):  // user.interviewCredits >= 1
  checkOptimize(user):   // user.resumeOptimizeCredits > 0
                         //   || user.freeOptimizeUsed < freeLimit
  checkDownload(user, resume):  // resume.paidDownload
                                //   || user.resumeDownloadCredits > 0

  deductInterview(user)
  deductOptimize(user)
  deductDownload(user, resume)
}

各类用户行为对应的检查

行为 检查条件 扣减项
开始 AI 面试 interviewCredits >= 1 interviewCredits -= 1
AI 诊断/优化简历 resumeOptimizeCredits > 0 || freeOptimizeUsed < 3 付费优先扣,免费次之
下载简历 PDF resume.paidDownload || resumeDownloadCredits > 0 标记 resume.paidDownload

支付流程扩展

现有:套餐购买(不变)

POST /payment/create { plan: 'growth' | 'sprint' }
  → 创建 Membership 订单(type='membership'
  → WeChat Pay
  → 回调/activate → 注入 plan 对应的全部 credits

新增:按次购买

POST /payment/create-product { type, resumeId?, count? }
  → 从 pricing config 读取单价
  → 创建对应 type 订单
  → WeChat Pay
  → 回调 → 根据 type 增加对应用户 credits / 标记下载

支持的产品:

  • interview:增加 interviewCredits
  • optimize:增加 resumeOptimizeCredits
  • download:标记 resume.paidDownload=true

数字人面试架构

整体流程

用户选择岗位 → 配额检查 → AI 出题 → 回答
  → AI 评分+下一题 → ... → 完成 → 报告 → 头像回顾视频(可选)

每次 AI 回复时,同步调用 TTS 生成音频,返回给前端:

// 面试回答响应
{
  text: "请介绍一下你的项目经验",
  audioUrl: "/tts/cache/abc123.mp3",  // edge-tts 生成
  durationMs: 2800,                    // 音频时长
  animationTimings: [],                // 可选:逐字时间戳
}

TTS 服务

backend/src/modules/tts/tts.service.ts

class TtsService {
  async synthesize(text: string): Promise<{ audioPath: string; durationMs: number }> {
    // 1. 按 text MD5 检查缓存
    // 2. 未命中 → child_process.exec('edge-tts ...')
    // 3. 保存到 /tmp/tts-cache/ 或 certs 同目录
    // 4. 返回路径和时长
  }
}

edge-tts 命令示例:

edge-tts --voice zh-CN-XiaoxiaoNeural --text "你好" --write-media /tmp/tts-cache/abc.mp3

前端数字人组件

zhiyin-app/src/components/digital-human.vue

┌─────────────────────┐
│     ┌───────┐       │
│     │ 头像   │       │  ← 静态 PNG + CSS呼吸/眨眼
│     │ (嘴型) │       │  ← Canvas 覆盖嘴部区域
│     └───────┘       │
│   "请介绍你的项目"    │  ← 字幕气泡
│                     │
│  [▼ 音频波形]       │  ← 可选
└─────────────────────┘

嘴型驱动:

  1. AudioContext.createMediaElementSource(audioEl)AnalyserNode
  2. 每帧读取 analyser.getByteTimeDomainData(dataArray)
  3. 计算 RMS → 映射到嘴型开合度 (0~1)
  4. Canvas 绘制椭圆(开)或线(闭)

新接口

方法 路径 说明
POST /interview/create-avatar 创建数字人面试(含配额检查)
POST /interview/:id/answer-avatar 回答+AI 回复(含 TTS audioUrl
GET /tts/:hash 获取 TTS 音频文件

简历下载流程图

用户查看优化结果
  │
  ├─ 点击「下载 PDF」
  │    │
  │    ├─ resume.paidDownload === true → 直接生成 → 返回 PDF
  │    │
  │    └─ resume.paidDownload === false
  │         │
  │         ├─ user.resumeDownloadCredits > 0
  │         │   → 扣 1 credit → 标记 paidDownload → 生成 PDF
  │         │
  │         └─ 无 credits
  │             → 弹出支付窗口(¥X/次)
  │             → WeChat Pay → 标记 paidDownload → 生成 PDF
  │
  └─ 再次优化(内容改变)
      → contentHash 变化 → 新 resume 记录(version++
      → paidDownload = false
      → 需重新付费下载

Puppeteer PDF 生成 (resume-pdf.service.ts)

  1. 读取 resume.contentmarkdown/HTML
  2. 套用模板(含姓名、岗位、日期等)
  3. puppeteer.launch()page.setContent(html)page.pdf({ format: 'A4' })
  4. 返回 PDF buffer
  5. 可选:同时生成 Word(用 HTML → mammoth 或 libreoffice

管理后台配置

在现有 admin.vue 的 Config Tab 中增加:

┌─────────────────────────────────────────────┐
│  定价配置                          [保存]   │
│                                             │
│  AI 面试单价          ¥ [ 5  ] /次          │
│  简历优化单价          ¥ [ 3  ] /次          │
│  简历下载单价          ¥ [ 2  ] /次          │
│  免费优化次数          [ 3  ] 次             │
│  首次面试免费          [✓]                   │
│                                             │
│  ─── 成长版 ───                             │
│  价格                ¥ [ 19.9 ] /月         │
│  面试额度              [ 999  ] 次           │
│  优化额度              [ 20   ] 次           │
│  下载额度              [ 10   ] 次           │
│  功能列表              [编辑]                │
│                                             │
│  ─── 冲刺版 ───                             │
│  ...                                        │
└─────────────────────────────────────────────┘

实施优先级

阶段 内容 文件涉及
P0-1 定价配置化 + User 新字段 + 统一配额检查 user.schema, SiteConfig, QuotaService
P0-2 简历下载付费 + Puppeteer PDF resume.schema, resume.service, resume.controller, ResumePdfService
P0-3 支付扩展(按次购买) payment-order.schema, payment.controller
P1-1 TTS 服务 tts.service, tts.controller, tts.module
P1-2 数字人面试前端组件 digital-human.vue, interview.vue
P1-3 面试接口改版 + 配额接入 interview.service, interview.controller
P2 Admin 定价管理界面 admin.vue, admin.controller

兼容性注意事项

  • remaining 字段保留,老用户数据不受影响
  • 新用户注册默认 interviewCredits=1(首次免费)
  • 会员激活时注入 plan 定义的 credits
  • 过期降级时不清零已购买的 credits,仅阻止会员专属 privileges
  • 已购买的单次 credits 不过期