feat: 付费体系重构 P0 - 配额独立化/简历付费下载/PDF生成
This commit is contained in:
@@ -8,6 +8,7 @@ import { User, UserDocument } from '../user/user.schema'
|
||||
import { Interview, InterviewDocument } from '../interview/interview.schema'
|
||||
import { PaymentOrder, PaymentOrderDocument } from '../payment/payment-order.schema'
|
||||
import { SiteConfig, SiteConfigDocument } from '../schemas/site-config.schema'
|
||||
import { QuotaService } from '../user/quota.service'
|
||||
import { WechatPayService } from '../payment/wechat-pay.service'
|
||||
|
||||
const VIP_DURATION_DAYS = 30
|
||||
@@ -20,6 +21,7 @@ export class AdminController {
|
||||
@InjectModel(Interview.name) private interviewModel: Model<InterviewDocument>,
|
||||
@InjectModel(PaymentOrder.name) private orderModel: Model<PaymentOrderDocument>,
|
||||
@InjectModel(SiteConfig.name) private configModel: Model<SiteConfigDocument>,
|
||||
private quotaService: QuotaService,
|
||||
private wechatPay: WechatPayService,
|
||||
) {}
|
||||
|
||||
@@ -82,8 +84,7 @@ export class AdminController {
|
||||
expireAt.setDate(expireAt.getDate() + VIP_DURATION_DAYS)
|
||||
user.plan = 'growth'
|
||||
user.vipExpireAt = expireAt
|
||||
user.remaining = 999
|
||||
await user.save()
|
||||
await this.quotaService.setPlanQuota(targetUserId, 'growth', { interview: 999, resumeOptimize: 20, resumeDownload: 10 })
|
||||
return { success: true, plan: 'growth', expireAt }
|
||||
}
|
||||
|
||||
@@ -126,14 +127,20 @@ export class AdminController {
|
||||
order.wxTransactionId = wxResult?.transaction_id || ''
|
||||
order.paidAt = new Date()
|
||||
await order.save()
|
||||
const user = await this.userModel.findById(order.userId).exec()
|
||||
if (user && user.plan === 'free') {
|
||||
const expireAt = new Date()
|
||||
expireAt.setDate(expireAt.getDate() + VIP_DURATION_DAYS)
|
||||
user.plan = 'growth'
|
||||
user.vipExpireAt = expireAt
|
||||
user.remaining = 999
|
||||
await user.save()
|
||||
if (order.type === 'membership') {
|
||||
const user = await this.userModel.findById(order.userId).exec()
|
||||
if (user && user.plan === 'free') {
|
||||
const expireAt = new Date()
|
||||
expireAt.setDate(expireAt.getDate() + VIP_DURATION_DAYS)
|
||||
user.plan = 'growth'
|
||||
user.vipExpireAt = expireAt
|
||||
await this.quotaService.setPlanQuota(order.userId, 'growth', { interview: 999, resumeOptimize: 20, resumeDownload: 10 })
|
||||
}
|
||||
} else {
|
||||
const credits = { interview: 1, optimize: 1, download: 1 }[order.type]
|
||||
if (credits) {
|
||||
await this.quotaService.grantCredits(order.userId, order.type as any, credits)
|
||||
}
|
||||
}
|
||||
}
|
||||
return { order, wxResult }
|
||||
@@ -179,8 +186,8 @@ const DEFAULT_CONFIG = {
|
||||
optimize: { dailyFreeLimit: 2 },
|
||||
price: { monthly: 1990 },
|
||||
plans: {
|
||||
free: { name: '免费版', price: 0, features: ['每日 3 次 AI 模拟面试', '每场最多 5 轮 AI 对话', '基础面试报告', '简历诊断', '简历优化'] },
|
||||
growth: { name: '成长版', price: 1990, features: ['免费版全部权益', '无限面试次数', '每场最多 10 轮 AI 对话', '详细面试报告(四维评分)', '进步轨迹雷达图 + 打卡', '参考回答思路', '公司真题库'] },
|
||||
free: { name: '免费版', price: 0, features: ['AI 模拟面试 1 次(体验)', '每场最多 5 轮 AI 对话', '基础面试报告', '简历优化(限 3 次)'] },
|
||||
growth: { name: '成长版', price: 1990, features: ['免费版全部权益', 'AI 数字人面试无限次', '每场最多 10 轮 AI 对话', '详细面试报告(四维评分)', '进步轨迹雷达图 + 打卡', '参考回答思路', '公司真题库', '简历优化 20 次/月', '简历下载 10 次/月'] },
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ import { Module } from '@nestjs/common'
|
||||
import { MongooseModule } from '@nestjs/mongoose'
|
||||
import { AdminController } from './admin.controller'
|
||||
import { User, UserSchema } from '../user/user.schema'
|
||||
import { UserModule } from '../user/user.module'
|
||||
import { Interview, InterviewSchema } from '../interview/interview.schema'
|
||||
import { PaymentOrder, PaymentOrderSchema } from '../payment/payment-order.schema'
|
||||
import { WechatPayService } from '../payment/wechat-pay.service'
|
||||
@@ -16,6 +17,7 @@ import { SiteConfig, SiteConfigSchema } from '../schemas/site-config.schema'
|
||||
{ name: PaymentOrder.name, schema: PaymentOrderSchema },
|
||||
{ name: SiteConfig.name, schema: SiteConfigSchema },
|
||||
]),
|
||||
UserModule,
|
||||
],
|
||||
controllers: [AdminController],
|
||||
providers: [WechatPayService, AdminGuard],
|
||||
|
||||
Reference in New Issue
Block a user