本文引用的文件
本文件面向AI有声书生成平台的用户会员信息模型,系统性阐述以下关键字段与业务逻辑:
重点解释会员等级制度、使用量统计机制、订阅周期计算,并说明这些字段如何协同实现会员权益管理与使用限制。同时提供会员状态查询、等级升级、使用量统计等核心功能的实现路径与算法流程图,帮助开发者快速定位与扩展相关能力。
会员与订阅相关的核心代码分布在服务层、控制器层、中间件与类型定义中,数据库模型由Prisma Schema定义。
graph TB
subgraph "前端"
UI["页面/接口调用"]
end
subgraph "后端"
CTRL_MEMBER["member.controller.ts<br/>会员接口路由"]
SVC_MEMBER["member.service.ts<br/>会员状态/订单/支付模拟"]
CTRL_SUB["subscription.controller.ts<br/>订阅接口路由"]
SVC_SUB["subscription.service.ts<br/>订阅/配额/计费/用量"]
MW_USAGE["usageLimit.ts<br/>每日使用次数限制中间件"]
TYPES["types/index.ts<br/>类型与配额常量"]
PRISMA["prisma/schema.prisma<br/>数据库模型"]
end
UI --> CTRL_MEMBER
UI --> CTRL_SUB
CTRL_MEMBER --> SVC_MEMBER
CTRL_SUB --> SVC_SUB
SVC_MEMBER --> PRISMA
SVC_SUB --> PRISMA
MW_USAGE --> PRISMA
SVC_MEMBER --> TYPES
SVC_SUB --> TYPES
图表来源
章节来源
章节来源
会员与订阅模块通过控制器暴露REST接口,服务层封装业务规则,中间件在入口处进行使用限制校验,Prisma负责数据持久化。
sequenceDiagram
participant Client as "客户端"
participant CtrlMember as "会员控制器"
participant SvcMember as "会员服务"
participant CtrlSub as "订阅控制器"
participant SvcSub as "订阅服务"
participant DB as "数据库(Prisma)"
Client->>CtrlMember : GET /member/status
CtrlMember->>SvcMember : getMemberStatus(userId)
SvcMember->>DB : 查询User(含memberLevel/dailyUsage/lastUsageDate)
DB-->>SvcMember : 返回用户数据
SvcMember-->>CtrlMember : 返回会员状态
CtrlMember-->>Client : 状态响应
Client->>CtrlSub : GET /subscription/audio-balance
CtrlSub->>SvcSub : getUserAudioBalance(userId)
SvcSub->>DB : 查询User(含usedAudioMinutes/subscriptionResetDate)
DB-->>SvcSub : 返回用户数据
SvcSub-->>CtrlSub : 返回音频余额
CtrlSub-->>Client : 余额响应
图表来源
状态判定
日常重置:若 lastUsageDate 不等于今天,则 dailyUsage 清零
flowchart TD
Start(["进入 getMemberStatus"]) --> LoadUser["查询用户信息"]
LoadUser --> Today["获取今日日期(YYYY-MM-DD)"]
Today --> CheckReset{"lastUsageDate == 今日?"}
CheckReset -- 否 --> ResetDaily["dailyUsage = 0"]
CheckReset -- 是 --> KeepDaily["保持 dailyUsage"]
ResetDaily --> CalcQuota["根据 memberLevel 计算配额"]
KeepDaily --> CalcQuota
CalcQuota --> Valid{"memberLevel>0 且 memberExpireAt>now?"}
Valid -- 是 --> Ok["返回有效状态"]
Valid -- 否 --> Expired["返回无效状态"]
Ok --> End(["结束"])
Expired --> End
图表来源
章节来源
重置策略
以 lastUsageDate 与当前日期比较决定是否重置 dailyUsage
flowchart TD
Enter(["进入 usageLimitMiddleware"]) --> HasUserId{"存在userId?"}
HasUserId -- 否 --> Allow["设置无限制配额并放行"]
HasUserId -- 是 --> LoadUser["查询用户"]
LoadUser --> Today["获取今日日期"]
Today --> CheckLast{"lastUsageDate != 今日?"}
CheckLast -- 是 --> Update["更新 dailyUsage=0, lastUsageDate=今日"]
CheckLast -- 否 --> Skip["跳过重置"]
Update --> CheckQuota{"dailyUsage >= dailyLimit?"}
Skip --> CheckQuota
CheckQuota -- 是 --> Over["抛出配额超限错误"]
CheckQuota -- 否 --> Pass["放行到下一个中间件/处理器"]
图表来源
章节来源
算法流程
计算配额内价格与超额价格,得出总费用
flowchart TD
Start(["进入 getUserAudioBalance"]) --> LoadUser["查询用户"]
LoadUser --> GetLevel["获取 memberLevel 与月度配额"]
GetLevel --> CheckReset{"subscriptionResetDate 是否存在?"}
CheckReset -- 否 --> InitReset["初始化重置日期为当前时间"]
CheckReset -- 是 --> CompareMonth{"当前月份是否变化?"}
CompareMonth -- 是 --> Reset["usedAudioMinutes=0, 更新subscriptionResetDate"]
CompareMonth -- 否 --> Keep["保持原值"]
InitReset --> Compute["返回余额信息"]
Reset --> Compute
Keep --> Compute
Compute --> End(["结束"])
图表来源
章节来源
到期检测
会员状态的有效性由 memberLevel > 0 且 memberExpireAt 存在且当前时间早于过期时间决定
sequenceDiagram
participant Client as "客户端"
participant Ctrl as "会员控制器"
participant Svc as "会员服务"
participant DB as "数据库(Prisma)"
Client->>Ctrl : POST /member/order {productType}
Ctrl->>Svc : createOrder(userId, productType)
Svc->>DB : 创建订单
DB-->>Svc : 返回订单
Svc-->>Ctrl : 返回订单号与金额
Ctrl-->>Client : 订单创建成功
Client->>Ctrl : POST /member/pay/mock {orderNo}
Ctrl->>Svc : mockPaymentSuccess(orderNo, userId)
Svc->>DB : 查询订单与用户
Svc->>Svc : 计算到期时间(延续或从现在开始)
Svc->>DB : 更新用户memberLevel与memberExpireAt
DB-->>Svc : 更新成功
Svc-->>Ctrl : 返回升级结果
Ctrl-->>Client : 支付成功
图表来源
章节来源
扣费与记录
通过 consumeAudioMinutes 扣除音频时长并记录使用日志
flowchart TD
Start(["生成音频前"]) --> Estimate["getAudioEstimate(userId, textLength)"]
Estimate --> Check["checkAudioQuota(userId, textLength)"]
Check --> Allowed{"allowed?"}
Allowed -- 否 --> Deny["拒绝生成并提示原因"]
Allowed -- 是 --> Consume["consumeAudioMinutes(userId, textLength)"]
Consume --> Update["更新 usedAudioMinutes 并写入TokenUsage"]
Update --> Done(["完成"])
Deny --> Done
图表来源
章节来源
控制器依赖
member.controller.ts 与 subscription.controller.ts 分别调用对应服务方法
graph LR
Types["types/index.ts"] --> MemberSvc["member.service.ts"]
Types --> SubSvc["subscription.service.ts"]
Types --> UsageMW["usageLimit.ts"]
MemberSvc --> Prisma["prisma/schema.prisma"]
SubSvc --> Prisma
UsageMW --> Prisma
MemberCtrl["member.controller.ts"] --> MemberSvc
SubCtrl["subscription.controller.ts"] --> SubSvc
图表来源
章节来源
章节来源
本会员信息模型通过 memberLevel、memberExpireAt、dailyUsage、usedAudioMinutes、subscriptionResetDate 等字段,结合服务层的权益配置、使用限制中间件与订阅计费算法,实现了清晰的会员等级制度与使用量统计机制。开发者可基于现有接口与算法快速扩展新功能,如更细粒度的权限控制、多语言音色支持、阶梯定价策略等。