用户与订阅模型.md 23 KB

用户与订阅模型

本文引用的文件

  • member.controller.ts
  • member.service.ts
  • subscription.controller.ts
  • subscription.service.ts
  • auth.controller.ts
  • index.ts
  • index.ts
  • schema.prisma
  • Token计费系统设计.md
  • database-structure.md
  • API.md

目录

  1. 简介
  2. 项目结构
  3. 核心组件
  4. 架构总览
  5. 详细组件分析
  6. 依赖分析
  7. 性能考量
  8. 故障排查指南
  9. 结论
  10. 附录

简介

本文件面向AI有声书生成平台,系统化梳理“用户”“会员”“订阅计划”三者的关系与业务逻辑,覆盖用户等级管理、会员到期时间、每日使用量统计等用户属性;解释订阅计划的定价策略、会员权益、自动续费机制等订阅功能的数据结构;并提供用户注册登录流程、会员升级降级、订阅状态管理等业务场景的API使用示例,以及用户行为分析与会员转化率统计的实现思路。

项目结构

围绕用户与订阅模型,后端采用模块化分层:

  • 控制器层:负责HTTP路由与请求参数校验,例如会员模块的订单创建、状态查询,订阅模块的套餐查询、余额与用量查询等。
  • 服务层:封装业务逻辑,如会员权益计算、Token余额与用量、音频时长配额与计费、书籍生成配额估算等。
  • 数据访问层:通过Prisma连接MySQL,统一管理User、Order、SubscriptionPlan、Subscription、TokenBalance、TokenUsage等模型。
  • 类型与配置:统一定义用户类型、会员等级、Token计费配置、音频计费配置、套餐默认配置等。

    graph TB
    subgraph "控制器层"
    MC["member.controller.ts"]
    SC["subscription.controller.ts"]
    AC["auth.controller.ts"]
    end
    subgraph "服务层"
    MS["member.service.ts"]
    SS["subscription.service.ts"]
    end
    subgraph "数据访问层"
    PRISMA["PrismaClient(schema.prisma)"]
    MODELS["models/index.ts"]
    end
    subgraph "类型与配置"
    TYPES["types/index.ts"]
    DOCS1["Token计费系统设计.md"]
    DOCS2["database-structure.md"]
    DOCS3["API.md"]
    end
    MC --> MS
    SC --> SS
    AC --> MS
    MS --> PRISMA
    SS --> PRISMA
    PRISMA --> MODELS
    MS --> TYPES
    SS --> TYPES
    SS --> DOCS1
    MS --> DOCS2
    SC --> DOCS3
    

图表来源

  • member.controller.ts:1-90
  • subscription.controller.ts:1-191
  • auth.controller.ts:1-94
  • member.service.ts:1-183
  • subscription.service.ts:1-938
  • index.ts:1-15
  • index.ts:1-124
  • schema.prisma:1-472
  • Token计费系统设计.md:1-501
  • database-structure.md:1-402
  • API.md:1-499

章节来源

  • member.controller.ts:1-90
  • subscription.controller.ts:1-191
  • auth.controller.ts:1-94
  • member.service.ts:1-183
  • subscription.service.ts:1-938
  • index.ts:1-15
  • index.ts:1-124
  • schema.prisma:1-472
  • Token计费系统设计.md:1-501
  • database-structure.md:1-402
  • API.md:1-499

核心组件

  • User模型:承载用户基本信息、会员等级、会员到期时间、每日使用次数与日期、音频时长使用与重置时间等。
  • Order模型:记录会员购买订单,包含订单号、金额、状态、支付方式与时间等。
  • SubscriptionPlan模型:记录订阅套餐配置,包含月/年价格、功能特性、每日生成次数、单次字数上限、月度Token/分钟配额、是否支持超额及超额单价等。
  • Subscription模型:记录用户当前有效订阅,包含起止时间、状态、是否自动续费等。
  • TokenBalance与TokenUsage:记录Token余额、使用情况与明细。
  • 会员权益与配额:通过常量与服务函数统一管理不同会员等级的每日/单次/月度限额与权益。

章节来源

  • schema.prisma:10-38
  • schema.prisma:40-61
  • schema.prisma:254-284
  • schema.prisma:286-302
  • schema.prisma:304-332
  • index.ts:1-124
  • member.service.ts:1-183
  • subscription.service.ts:157-296

架构总览

用户与订阅模型在服务层通过Prisma进行统一读写,控制器层负责路由与鉴权,类型定义确保前后端一致性。下图展示了用户、会员与订阅的关键交互:

sequenceDiagram
participant Client as "客户端"
participant AuthCtrl as "auth.controller.ts"
participant MemberCtrl as "member.controller.ts"
participant SubCtrl as "subscription.controller.ts"
participant MemberSvc as "member.service.ts"
participant SubSvc as "subscription.service.ts"
participant DB as "Prisma(schema.prisma)"
Client->>AuthCtrl : POST /api/auth/login
AuthCtrl->>MemberSvc : 登录后获取会员状态
MemberSvc->>DB : 查询User
DB-->>MemberSvc : User
MemberSvc-->>AuthCtrl : 会员状态
AuthCtrl-->>Client : 返回token与用户信息
Client->>SubCtrl : GET /api/subscription/plans
SubCtrl->>SubSvc : 获取套餐列表
SubSvc->>DB : 查询SubscriptionPlan
DB-->>SubSvc : 套餐列表
SubSvc-->>SubCtrl : 套餐数据
SubCtrl-->>Client : 套餐列表
Client->>MemberCtrl : POST /api/member/order
MemberCtrl->>MemberSvc : 创建订单
MemberSvc->>DB : 创建Order
DB-->>MemberSvc : Order
MemberSvc-->>MemberCtrl : 订单号与金额
MemberCtrl-->>Client : 订单信息

图表来源

  • auth.controller.ts:32-52
  • member.controller.ts:32-48
  • subscription.controller.ts:9-18
  • member.service.ts:75-100
  • subscription.service.ts:311-324
  • schema.prisma:10-61

详细组件分析

用户模型与会员等级管理

  • 用户属性
    • 会员等级:0(免费)、1(月度会员)、2(年度会员)
    • 会员到期时间:memberExpireAt
    • 每日使用次数与日期:dailyUsage、lastUsageDate
    • 音频时长使用与重置:usedAudioMinutes、subscriptionResetDate
  • 会员状态计算

    • 若memberExpireAt存在且未过期,则视为有效
    • 每日首次访问会重置dailyUsage
    • 根据会员等级映射配额(每日/单次/字数限制)

      flowchart TD
      Start(["进入会员状态查询"]) --> LoadUser["加载User"]
      LoadUser --> Today["获取今日日期"]
      Today --> ResetCheck{"lastUsageDate != 今天?"}
      ResetCheck --> |是| ResetDaily["dailyUsage = 0"]
      ResetCheck --> |否| KeepDaily["保持dailyUsage不变"]
      ResetDaily --> CalcQuota["根据memberLevel计算配额"]
      KeepDaily --> CalcQuota
      CalcQuota --> ExpireCheck{"memberExpireAt存在且未过期?"}
      ExpireCheck --> |是| Valid["isValid = true"]
      ExpireCheck --> |否| Invalid["isValid = false"]
      Valid --> End(["返回状态"])
      Invalid --> End
      

图表来源

  • member.service.ts:39-73
  • index.ts:18-18
  • schema.prisma:10-24

章节来源

  • member.service.ts:39-73
  • index.ts:18-18
  • schema.prisma:10-24

订阅计划与定价策略

  • 套餐配置
    • 默认包含免费版、入门版、专业版、旗舰版、企业版
    • 每个套餐定义月/年价格、功能特性、每日生成次数、单次字数上限、月度Token/分钟配额、是否支持超额及超额单价
  • 初始化逻辑
    • 首次启动时若无套餐数据则批量插入默认套餐
  • 套餐查询

    • 按激活状态与排序返回套餐列表,解析features字符串为数组

      classDiagram
      class SubscriptionPlan {
      +int id
      +string name
      +int level
      +decimal priceMonthly
      +decimal priceYearly
      +string description
      +string features
      +bool isRecommended
      +bool isActive
      +int sortOrder
      +int dailyGenerations
      +int perGenerationLimit
      +int monthlyTokens
      +int monthlyMinutes
      +int? yearlyTokens
      +int voiceOptions
      +string audioQuality
      +bool apiAccess
      +bool batchProcessing
      +bool teamManagement
      +bool overageEnabled
      +decimal overagePrice
      }
      class Subscription {
      +int id
      +int userId
      +int planId
      +datetime startDate
      +datetime endDate
      +string status
      +bool autoRenew
      }
      Subscription --> SubscriptionPlan : "关联"
      

图表来源

  • subscription.service.ts:157-296
  • subscription.service.ts:298-309
  • schema.prisma:254-302

章节来源

  • subscription.service.ts:157-296
  • subscription.service.ts:298-309
  • schema.prisma:254-302

Token计费与音频时长计费

  • Token计费
    • 基于AI模型与TTS成本计算,提供建议售价与总成本
    • 用户Token余额与使用明细,支持检查与消费
  • 音频时长计费

    • 包月=批发价,按量=零售价
    • 每月1日重置配额,支持超额计费
    • 提供预估生成费用与可用时长

      flowchart TD
      Start(["生成音频请求"]) --> Estimate["估算音频时长"]
      Estimate --> QuotaCheck["检查月度配额"]
      QuotaCheck --> Allowed{"配额充足?"}
      Allowed --> |是| PriceCalc["计算包月内价格"]
      Allowed --> |否| OverageCheck{"支持超额?"}
      OverageCheck --> |是| OverageCalc["计算超额价格"]
      OverageCheck --> |否| Deny["拒绝生成"]
      PriceCalc --> Total["合计总费用"]
      OverageCalc --> Total
      Total --> Consume["扣除Token/更新用户时长"]
      Consume --> End(["返回结果"])
      Deny --> End
      

图表来源

  • subscription.service.ts:551-600
  • subscription.service.ts:651-683
  • subscription.service.ts:685-724
  • subscription.service.ts:726-766

章节来源

  • subscription.service.ts:551-600
  • subscription.service.ts:651-683
  • subscription.service.ts:685-724
  • subscription.service.ts:726-766
  • Token计费系统设计.md:1-501

会员升级与订单流程

  • 订单创建
    • 校验产品类型(monthly/yearly),生成唯一订单号,写入Order表
  • 模拟支付
    • 开发环境支持模拟支付成功,更新订单状态与用户会员等级与到期时间
  • 订单列表

    • 支持分页查询用户历史订单

      sequenceDiagram
      participant Client as "客户端"
      participant MemberCtrl as "member.controller.ts"
      participant MemberSvc as "member.service.ts"
      participant DB as "Prisma(schema.prisma)"
      Client->>MemberCtrl : POST /api/member/order
      MemberCtrl->>MemberSvc : createOrder(userId, productType)
      MemberSvc->>DB : 创建Order
      DB-->>MemberSvc : Order
      MemberSvc-->>MemberCtrl : {orderNo, amount}
      MemberCtrl-->>Client : 订单信息
      Client->>MemberCtrl : POST /api/member/pay/mock
      MemberCtrl->>MemberSvc : mockPaymentSuccess(orderNo, userId)
      MemberSvc->>DB : 更新Order状态
      MemberSvc->>DB : 更新User会员等级与到期时间
      DB-->>MemberSvc : 成功
      MemberSvc-->>MemberCtrl : {success, memberLevel, memberExpireAt}
      MemberCtrl-->>Client : 支付成功
      

图表来源

  • member.controller.ts:32-70
  • member.service.ts:75-155
  • schema.prisma:40-61
  • schema.prisma:10-38

章节来源

  • member.controller.ts:32-70
  • member.service.ts:75-155
  • schema.prisma:40-61
  • schema.prisma:10-38

订阅状态管理与API使用示例

  • 获取套餐列表与详情
    • GET /api/subscription/plans
    • GET /api/subscription/plans/:id
  • 获取用户订阅信息与Token余额
    • GET /api/subscription/subscription
    • GET /api/subscription/balance
  • 检查配额与书籍生成配额
    • POST /api/subscription/check-quota
    • GET /api/subscription/book-generation-quota
  • 音频时长余额与预估
    • GET /api/subscription/audio-balance
    • GET /api/subscription/audio-estimate

章节来源

  • subscription.controller.ts:9-191
  • API.md:1-499

用户注册登录流程

  • 发送验证码
    • POST /api/auth/send-code
  • 手机号登录
    • POST /api/auth/login
  • 获取/更新用户信息
    • GET /api/auth/user-info
    • PUT /api/auth/user-info

章节来源

  • auth.controller.ts:10-94
  • API.md:13-93

依赖分析

  • 控制器依赖服务:各控制器通过依赖注入的方式调用对应服务函数,职责清晰。
  • 服务依赖Prisma:服务层统一通过PrismaClient访问数据库,避免控制器直接操作数据。
  • 类型约束:通过types/index.ts中的接口与枚举,确保前后端一致的数据结构。
  • 配置与文档:Token计费与数据库结构文档作为设计依据,指导服务层实现。

    graph LR
    MC["member.controller.ts"] --> MS["member.service.ts"]
    SC["subscription.controller.ts"] --> SS["subscription.service.ts"]
    AC["auth.controller.ts"] --> MS
    MS --> PRISMA["Prisma(schema.prisma)"]
    SS --> PRISMA
    MS --> TYPES["types/index.ts"]
    SS --> TYPES
    SS --> DOCS1["Token计费系统设计.md"]
    MS --> DOCS2["database-structure.md"]
    SC --> DOCS3["API.md"]
    

图表来源

  • member.controller.ts:1-90
  • subscription.controller.ts:1-191
  • auth.controller.ts:1-94
  • member.service.ts:1-183
  • subscription.service.ts:1-938
  • index.ts:1-15
  • index.ts:1-124
  • schema.prisma:1-472
  • Token计费系统设计.md:1-501
  • database-structure.md:1-402
  • API.md:1-499

章节来源

  • member.controller.ts:1-90
  • subscription.controller.ts:1-191
  • auth.controller.ts:1-94
  • member.service.ts:1-183
  • subscription.service.ts:1-938
  • index.ts:1-15
  • index.ts:1-124
  • schema.prisma:1-472
  • Token计费系统设计.md:1-501
  • database-structure.md:1-402
  • API.md:1-499

性能考量

  • 数据库索引
    • User:phone、openid索引,便于登录与绑定
    • Order:userId、orderNo、status索引,提升订单查询与支付回调效率
    • TokenUsage:userId、createdAt、type索引,支撑用量统计与报表
  • 查询优化
    • 分页查询:订单列表、Token使用记录均支持分页
    • 条件过滤:按状态、时间范围过滤,避免全表扫描
  • 缓存与重置
    • 每月1日重置音频时长配额,减少跨月统计复杂度
    • 每日重置Token余额(若采用Token计费),降低并发冲突

[本节为通用性能建议,无需特定文件引用]

故障排查指南

  • 订单状态异常
    • 确认订单状态是否为pending,模拟支付仅对pending订单生效
    • 检查订单号与用户匹配关系
  • 会员状态不更新
    • 核对memberExpireAt是否过期,过期则需延长到期时间
    • 确认memberLevel与配额映射是否正确
  • Token余额不足
    • 检查TokenBalance与TokenUsage记录,确认是否被正确消费
    • 确认是否达到每日/单次/月度限额
  • 音频时长不足
    • 检查usedAudioMinutes与subscriptionResetDate是否按月重置
    • 确认是否支持超额且超额单价设置正确

章节来源

  • member.service.ts:102-155
  • subscription.service.ts:602-649
  • subscription.service.ts:410-450

结论

本平台通过User、Order、SubscriptionPlan、Subscription、TokenBalance与TokenUsage等模型,构建了完善的用户与订阅管理体系。会员等级与到期时间、每日使用量统计、Token与音频时长双重计费策略,既保障用户体验,又实现可持续的商业化闭环。配套的API与文档为前端与运营提供了清晰的接入与分析路径。

[本节为总结性内容,无需特定文件引用]

附录

数据模型概览

erDiagram
USER {
int id PK
string phone
string openid
string nickname
string avatar
int memberLevel
datetime memberExpireAt
int dailyUsage
string lastUsageDate
int usedAudioMinutes
datetime subscriptionResetDate
datetime createdAt
datetime updatedAt
}
ORDER {
int id PK
int userId FK
string orderNo UK
int? planId FK
string productType
decimal amount
string status
string? paymentMethod
datetime? paidAt
datetime createdAt
datetime updatedAt
}
SUBSCRIPTION_PLAN {
int id PK
string name
int level
decimal priceMonthly
decimal priceYearly
string description
string features
bool isRecommended
bool isActive
int sortOrder
int dailyGenerations
int perGenerationLimit
int monthlyTokens
int monthlyMinutes
int? yearlyTokens
int voiceOptions
string audioQuality
bool apiAccess
bool batchProcessing
bool teamManagement
bool overageEnabled
decimal overagePrice
}
SUBSCRIPTION {
int id PK
int userId FK
int planId FK
datetime startDate
datetime endDate
string status
bool autoRenew
datetime createdAt
datetime updatedAt
}
TOKEN_BALANCE {
int id PK
int userId UK FK
int totalTokens
int usedTokens
datetime? resetDate
datetime createdAt
datetime updatedAt
}
TOKEN_USAGE {
int id PK
int userId FK
string type
int amount
int contentLength
int? orderId FK
string? description
datetime createdAt
}
USER ||--o{ ORDER : "has"
USER ||--o{ SUBSCRIPTION : "has"
USER ||--o{ TOKEN_BALANCE : "has"
USER ||--o{ TOKEN_USAGE : "has"
SUBSCRIPTION_PLAN ||--o{ SUBSCRIPTION : "defines"
ORDER ||--o{ TOKEN_USAGE : "records"

图表来源

  • schema.prisma:10-332

API使用示例(节选)

  • 注册登录
    • POST /api/auth/send-code
    • POST /api/auth/login
    • GET /api/auth/user-info
  • 会员模块
    • GET /api/member/benefits
    • GET /api/member/status
    • POST /api/member/order
    • POST /api/member/pay/mock
    • GET /api/member/orders
  • 订阅模块
    • GET /api/subscription/plans
    • GET /api/subscription/plans/:id
    • GET /api/subscription/subscription
    • GET /api/subscription/balance
    • GET /api/subscription/quota
    • POST /api/subscription/check-quota
    • GET /api/subscription/book-scale-estimate
    • GET /api/subscription/book-generation-quota
    • POST /api/subscription/check-quota-words
    • GET /api/subscription/audio-balance
    • GET /api/subscription/audio-estimate

章节来源

  • API.md:1-499
  • auth.controller.ts:10-94
  • member.controller.ts:9-88
  • subscription.controller.ts:9-191