Explorar el Código

feat: 确定最终定价方案 - 包月批发+按量零售

定价策略:
- 成本: ¥4/分钟
- 包月批发价: ¥5/分钟(30%利润)
- 按量零售价: ¥8/分钟(100%利润)

套餐设计:
- 免费版: ¥0,10分钟,不支持超出
- 入门版: ¥19,30分钟,超出¥8/分钟
- 专业版: ¥59,100分钟,超出¥7/分钟
- 旗舰版: ¥199,400分钟,超出¥6/分钟
- 企业版: ¥599,1500分钟,超出¥5/分钟

包月额度用完后可按量购买,按量价格更高(零售价)
MyFramework User hace 4 meses
padre
commit
10b11d3794

+ 24 - 0
agent-progress.txt

@@ -226,3 +226,27 @@ feature_list_optimize.json 所有30个功能已完成
 - [ ] npx prisma db push 更新数据库
 - [ ] 更新前端预估成本UI
 - [ ] 集成到TTS生成流程
+
+=== 2026-04-12 最终定价方案确定 ===
+
+【定价策略:包月=批发价,按量=零售价】
+- 成本: ¥4/分钟
+- 包月批发价: ¥5/分钟(30%利润)
+- 按量零售价: ¥8/分钟(100%利润)
+
+【套餐设计】
+| 套餐 | 月费 | 额度 | 超出单价 |
+|------|------|------|---------|
+| 免费版 | ¥0 | 10分钟 | 不支持 |
+| 入门版 | ¥19 | 30分钟 | ¥8/分钟 |
+| 专业版 | ¥59 | 100分钟 | ¥7/分钟 |
+| 旗舰版 | ¥199 | 400分钟 | ¥6/分钟 |
+| 企业版 | ¥599 | 1500分钟 | ¥5/分钟 |
+
+【更新文件】
+✅ server/src/modules/subscription/subscription.service.ts
+   - AUDIO_BILLING_CONFIG: 更新定价配置
+   - DEFAULT_PLANS: 更新5个套餐
+   - calculateAudioCost(): 支持配额内/超额分开计算
+
+✅ feature_list_subscription.json: 更新完整配置

+ 73 - 61
feature_list_subscription.json

@@ -8,22 +8,26 @@
     "auth_enabled": false
   },
   "design_overview": {
-    "problem": "当前按Token计费,用户不理解",
-    "solution": "改为按音频时长计费,用户直接知道'这段音频要花多少钱'"
+    "problem": "用户付费是为了得到音频文件",
+    "solution": "按音频时长计费,包月=批发价,按量=零售价"
   },
   "billing_model": {
     "unit": "音频时长(分钟)",
     "formula": "生成费用 = 音频时长 × 单价",
     "speaking_rate": 150,
-    "speaking_unit": "字/分钟"
+    "cost_per_minute": 4.0,
+    "pricing_strategy": {
+      "monthly": "包月批发价 ¥5/分钟(30%利润)",
+      "pay_as_you_go": "按量零售价 ¥8/分钟(100%利润)"
+    }
   },
   "pricing_plan": {
     "last_updated": "2026-04-12",
     "billing_unit": "audio_minutes",
-    "price_per_minute": {
-      "standard": 0.5,
-      "high": 1.0,
-      "lossless": 2.0
+    "core_pricing": {
+      "cost": 4.0,
+      "monthly_price": 5.0,
+      "overage_price": 8.0
     },
     "tiers": [
       {
@@ -35,7 +39,7 @@
         "description": "适合轻度体验",
         "features": [
           "每天3次生成",
-          "每月30分钟音频",
+          "每月10分钟音频",
           "每次最多2分钟",
           "基础音色5种",
           "标准音质"
@@ -43,28 +47,25 @@
         "limits": {
           "daily_generations": 3,
           "per_generation_limit": 300,
-          "monthly_minutes": 30,
-          "monthly_tokens": 3000,
-          "voice_options": 5,
-          "audio_quality": "standard"
+          "monthly_minutes": 10,
+          "overage_enabled": false
         },
-        "cost_analysis": {
-          "minutes_cost": 10.2,
-          "profit": -10.2,
-          "strategy": "平台补贴引流"
+        "pricing": {
+          "in_quota": "¥5/分钟",
+          "overage": "不支持超出"
         }
       },
       {
         "id": 1,
         "name": "入门版",
-        "price": 9.9,
-        "price_monthly": 9.9,
-        "price_yearly": 99,
-        "description": "适合日常使用",
+        "price": 19,
+        "price_monthly": 19,
+        "price_yearly": 190,
+        "description": "适合轻度使用",
         "recommended": false,
         "features": [
           "每天10次生成",
-          "每月100分钟音频",
+          "每月30分钟音频",
           "每次最多5分钟",
           "全部音色",
           "高清音质"
@@ -72,46 +73,38 @@
         "limits": {
           "daily_generations": 10,
           "per_generation_limit": 750,
-          "monthly_minutes": 100,
-          "monthly_tokens": 15000,
-          "voice_options": -1,
-          "audio_quality": "high"
+          "monthly_minutes": 30,
+          "overage_enabled": true
         },
-        "cost_analysis": {
-          "minutes_cost": 100,
-          "profit": -90.1,
-          "strategy": "亏损获客转化"
+        "pricing": {
+          "in_quota": "¥5/分钟",
+          "overage": "¥8/分钟"
         }
       },
       {
         "id": 2,
         "name": "专业版",
-        "price": 49,
-        "price_monthly": 49,
-        "price_yearly": 490,
+        "price": 59,
+        "price_monthly": 59,
+        "price_yearly": 590,
         "description": "适合内容创作者 ⭐推荐",
         "recommended": true,
         "features": [
           "无限制生成",
-          "每月500分钟音频",
-          "每次最多20分钟",
+          "每月100分钟音频",
+          "每次最多10分钟",
           "全部音色+定制音色",
-          "无损音质",
-          "VIP优先队列"
+          "高清音质"
         ],
         "limits": {
           "daily_generations": -1,
-          "per_generation_limit": 3000,
-          "monthly_minutes": 500,
-          "monthly_tokens": 75000,
-          "voice_options": -1,
-          "audio_quality": "lossless",
-          "api_access": false
+          "per_generation_limit": 1500,
+          "monthly_minutes": 100,
+          "overage_enabled": true
         },
-        "cost_analysis": {
-          "minutes_cost": 500,
-          "profit": -451,
-          "strategy": "亏损转化,盈利靠续费"
+        "pricing": {
+          "in_quota": "¥5/分钟",
+          "overage": "¥7/分钟"
         }
       },
       {
@@ -119,15 +112,41 @@
         "name": "旗舰版",
         "price": 199,
         "price_monthly": 199,
-        "price_yearly": 1999,
+        "price_yearly": 1990,
+        "description": "适合重度使用",
+        "recommended": false,
+        "features": [
+          "无限制生成",
+          "每月400分钟音频",
+          "每次最多20分钟",
+          "全部音色+定制音色",
+          "高清音质",
+          "VIP优先队列"
+        ],
+        "limits": {
+          "daily_generations": -1,
+          "per_generation_limit": 3000,
+          "monthly_minutes": 400,
+          "overage_enabled": true
+        },
+        "pricing": {
+          "in_quota": "¥5/分钟",
+          "overage": "¥6/分钟"
+        }
+      },
+      {
+        "id": 4,
+        "name": "企业版",
+        "price": 599,
+        "price_monthly": 599,
+        "price_yearly": 5990,
         "description": "适合企业用户",
         "recommended": false,
         "features": [
           "无限制生成",
-          "每月2000分钟音频",
+          "每月1500分钟音频",
           "每次最多60分钟",
           "全部功能",
-          "无损音质",
           "专属技术支持",
           "批量处理",
           "团队管理"
@@ -135,19 +154,12 @@
         "limits": {
           "daily_generations": -1,
           "per_generation_limit": 9000,
-          "monthly_minutes": 2000,
-          "monthly_tokens": 300000,
-          "voice_options": -1,
-          "audio_quality": "lossless",
-          "api_access": true,
-          "batch_processing": true,
-          "team_management": true
+          "monthly_minutes": 1500,
+          "overage_enabled": true
         },
-        "cost_analysis": {
-          "minutes_cost": 680,
-          "profit": -481,
-          "suggestion": "建议定价¥699-999/月",
-          "strategy": "高端定位"
+        "pricing": {
+          "in_quota": "¥5/分钟",
+          "overage": "¥5/分钟"
         }
       }
     ]

+ 190 - 108
server/src/modules/subscription/subscription.service.ts

@@ -154,7 +154,7 @@ export function calculateTokenCost(textLength: number, model: string = 'deepseek
   };
 }
 
-// 默认套餐配置(基于音频时长,2026-04-12更新
+// 默认套餐配置(包月批发+按量零售,2026-04-12定稿
 export const DEFAULT_PLANS = [
   {
     name: '免费版',
@@ -164,132 +164,164 @@ export const DEFAULT_PLANS = [
     description: '适合轻度体验',
     features: JSON.stringify([
       '每天3次生成',
-      '每月30分钟音频',
+      '每月10分钟音频',
       '每次最多2分钟',
       '基础音色5种',
-      '标准音质',
-      '科大讯飞TTS(免费额度)'
+      '标准音质'
     ]),
     isRecommended: false,
     sortOrder: 0,
     dailyGenerations: 3,
     perGenerationLimit: 300,       // ~2分钟音频
-    monthlyTokens: 3000,           // 文本配额
-    monthlyMinutes: 30,             // 音频时长配额(新增)
+    monthlyTokens: 1500,
+    monthlyMinutes: 10,            // 音频时长配额
     yearlyTokens: null,
     voiceOptions: 5,
     audioQuality: 'standard',
     apiAccess: false,
     batchProcessing: false,
     teamManagement: false,
-    costAnalysis: {
-      minutesCost: 10.2,           // 30分钟 × ¥0.34
-      platformSubsidy: true,
-      strategy: '平台补贴引流'
+    overageEnabled: false,        // 不支持超出配额
+    overagePrice: 0,
+    pricing: {
+      monthlyPricePerMinute: 5.0,  // ¥5/分钟(包月)
+      overagePricePerMinute: null  // 不支持按量
     }
   },
   {
     name: '入门版',
     level: 1,
-    priceMonthly: 9.9,
-    priceYearly: 99,
-    description: '适合日常使用',
+    priceMonthly: 19,
+    priceYearly: 190,
+    description: '适合轻度使用',
     features: JSON.stringify([
       '每天10次生成',
-      '每月100分钟音频',
+      '每月30分钟音频',
       '每次最多5分钟',
       '全部音色',
       '高清音质',
-      '百度基础版TTS'
+      '超出¥8/分钟'
     ]),
     isRecommended: false,
     sortOrder: 1,
     dailyGenerations: 10,
     perGenerationLimit: 750,       // ~5分钟音频
-    monthlyTokens: 15000,
-    monthlyMinutes: 100,           // 音频时长配额(新增)
+    monthlyTokens: 4500,
+    monthlyMinutes: 30,
     yearlyTokens: null,
     voiceOptions: -1,
     audioQuality: 'high',
     apiAccess: false,
     batchProcessing: false,
     teamManagement: false,
-    costAnalysis: {
-      minutesCost: 100,           // 100分钟 × ¥1.0
-      monthlyPrice: 9.9,
-      loss: -90.1,
-      strategy: '亏损获客转化'
+    overageEnabled: true,
+    overagePrice: 8.0,            // 超出¥8/分钟(零售价)
+    pricing: {
+      monthlyPricePerMinute: 5.0,  // ¥5/分钟(批发)
+      overagePricePerMinute: 8.0   // ¥8/分钟(零售)
     }
   },
   {
     name: '专业版',
     level: 2,
-    priceMonthly: 49,
-    priceYearly: 490,
+    priceMonthly: 59,
+    priceYearly: 590,
     description: '适合内容创作者 ⭐推荐',
     features: JSON.stringify([
       '无限制生成',
-      '每月500分钟音频',
-      '每次最多20分钟',
+      '每月100分钟音频',
+      '每次最多10分钟',
       '全部音色+定制音色',
-      '无损音质',
-      '百度精品版TTS',
-      'VIP优先队列'
+      '高清音质',
+      '超出¥7/分钟'
     ]),
     isRecommended: true,
     sortOrder: 2,
     dailyGenerations: -1,
-    perGenerationLimit: 3000,     // ~20分钟音频
-    monthlyTokens: 75000,
-    monthlyMinutes: 500,          // 音频时长配额(新增)
+    perGenerationLimit: 1500,      // ~10分钟音频
+    monthlyTokens: 15000,
+    monthlyMinutes: 100,
     yearlyTokens: null,
     voiceOptions: -1,
-    audioQuality: 'lossless',
+    audioQuality: 'high',
     apiAccess: false,
     batchProcessing: false,
     teamManagement: false,
-    costAnalysis: {
-      minutesCost: 500,           // 500分钟 × ¥1.0
-      monthlyPrice: 49,
-      loss: -451,
-      strategy: '亏损转化,盈利靠续费'
+    overageEnabled: true,
+    overagePrice: 7.0,            // 超出¥7/分钟
+    pricing: {
+      monthlyPricePerMinute: 5.0,
+      overagePricePerMinute: 7.0
     }
   },
   {
     name: '旗舰版',
     level: 3,
     priceMonthly: 199,
-    priceYearly: 1999,
+    priceYearly: 1990,
+    description: '适合重度使用',
+    features: JSON.stringify([
+      '无限制生成',
+      '每月400分钟音频',
+      '每次最多20分钟',
+      '全部音色+定制音色',
+      '高清音质',
+      'VIP优先队列',
+      '超出¥6/分钟'
+    ]),
+    isRecommended: false,
+    sortOrder: 3,
+    dailyGenerations: -1,
+    perGenerationLimit: 3000,      // ~20分钟音频
+    monthlyTokens: 60000,
+    monthlyMinutes: 400,
+    yearlyTokens: null,
+    voiceOptions: -1,
+    audioQuality: 'high',
+    apiAccess: true,
+    batchProcessing: false,
+    teamManagement: false,
+    overageEnabled: true,
+    overagePrice: 6.0,            // 超出¥6/分钟
+    pricing: {
+      monthlyPricePerMinute: 5.0,
+      overagePricePerMinute: 6.0
+    }
+  },
+  {
+    name: '企业版',
+    level: 4,
+    priceMonthly: 599,
+    priceYearly: 5990,
     description: '适合企业用户',
     features: JSON.stringify([
       '无限制生成',
-      '每月2000分钟音频',
+      '每月1500分钟音频',
       '每次最多60分钟',
       '全部功能',
-      '无损音质',
-      '火山引擎豆包TTS',
+      '高清音质',
       '专属技术支持',
       '批量处理',
-      '团队管理'
+      '团队管理',
+      '超出¥5/分钟'
     ]),
     isRecommended: false,
-    sortOrder: 3,
+    sortOrder: 4,
     dailyGenerations: -1,
     perGenerationLimit: 9000,      // ~60分钟音频
-    monthlyTokens: 300000,
-    monthlyMinutes: 2000,         // 音频时长配额(新增)
+    monthlyTokens: 225000,
+    monthlyMinutes: 1500,
     yearlyTokens: null,
     voiceOptions: -1,
-    audioQuality: 'lossless',
+    audioQuality: 'high',
     apiAccess: true,
     batchProcessing: true,
     teamManagement: true,
-    costAnalysis: {
-      minutesCost: 680,           // 2000分钟 × ¥0.34
-      monthlyPrice: 199,
-      loss: -481,
-      suggestion: '建议定价¥699-999/月',
-      strategy: '高端定位,低价策略'
+    overageEnabled: true,
+    overagePrice: 5.0,            // 超出¥5/分钟(最低零售价)
+    pricing: {
+      monthlyPricePerMinute: 5.0,
+      overagePricePerMinute: 5.0
     }
   }
 ];
@@ -512,41 +544,53 @@ export async function checkQuota(userId: number, requiredTokens: number) {
 }
 
 // ============================================
-// 音频时长计费系统(2026-04-12 新增
+// 音频时长计费系统(2026-04-12 定稿
 // ============================================
 
 export const AUDIO_BILLING_CONFIG = {
+  // 成本配置(综合TTS+AI成本)
+  costPerMinute: 4.0,  // 成本:¥4/分钟(AI文本生成+TTS合成)
+  
+  // 定价策略:包月=批发价,按量=零售价
+  pricing: {
+    // 包月(批发价)
+    monthly: {
+      basePricePerMinute: 5.0,  // ¥5/分钟(30%利润)
+    },
+    // 按量(零售价)
+    payAsYouGo: {
+      pricePerMinute: 8.0,     // ¥8/分钟(100%利润)
+    }
+  },
+  
   // 语速配置(字/分钟)
-  speakingRate: 150,  // 平均语速150字/分钟
+  speakingRate: 150,
   
-  // 音频时长单价(元/分钟)
-  pricePerMinute: {
-    standard: 0.5,    // 标准音质:¥0.5/分钟
-    high: 1.0,        // 高清音质:¥1.0/分钟
-    lossless: 2.0     // 无损音质:¥2.0/分钟
+  // 各等级每月音频时长配额(分钟)
+  monthlyMinutes: {
+    0: 10,     // 免费版:10分钟/月
+    1: 30,     // 入门版:30分钟/月
+    2: 100,    // 专业版:100分钟/月
+    3: 400,    // 旗舰版:400分钟/月
+    4: 1500    // 企业版:1500分钟/月
   },
   
-  // 各等级每月音频时长配额
-  monthlyMinutes: {
-    0: 30,    // 免费版:30分钟/月
-    1: 100,   // 入门版:100分钟/月
-    2: 500,   // 专业版:500分钟/月
-    3: 2000   // 旗舰版:2000分钟/月
+  // 各等级超出配额单价(元/分钟)
+  overagePrice: {
+    0: null,       // 免费版:不支持超出
+    1: 8.0,        // 入门版:¥8/分钟
+    2: 7.0,        // 专业版:¥7/分钟
+    3: 6.0,        // 旗舰版:¥6/分钟
+    4: 5.0         // 企业版:¥5/分钟
   },
   
   // 各等级单次生成最大时长(分钟)
   maxMinutesPerGeneration: {
     0: 2,     // 免费版:2分钟/次
     1: 5,     // 入门版:5分钟/次
-    2: 20,    // 专业版:20分钟/次
-    3: 60     // 旗舰版:60分钟/次
-  },
-  
-  // 成本计算(用于内部核算)
-  costPerMinute: {
-    standard: 0.34,   // AI¥0.2 + TTS¥0.14 = ¥0.34/分钟
-    high: 1.0,        // AI¥0.2 + TTS¥0.8 = ¥1.0/分钟
-    lossless: 3.4     // AI¥0.4 + TTS¥3.0 = ¥3.4/分钟
+    2: 10,    // 专业版:10分钟/次
+    3: 20,    // 旗舰版:20分钟/次
+    4: 60     // 企业版:60分钟/次
   }
 };
 
@@ -555,29 +599,49 @@ export function calculateAudioDuration(textLength: number): number {
   return Math.ceil(textLength / AUDIO_BILLING_CONFIG.speakingRate);
 }
 
-// 计算音频生成费用
+// 计算音频生成费用(支持包月配额和按量计费)
 export function calculateAudioCost(
   textLength: number,
-  quality: 'standard' | 'high' | 'lossless' = 'high'
+  memberLevel: number = 0,
+  usedMinutes: number = 0
 ): {
   textLength: number;
   audioMinutes: number;
-  pricePerMinute: number;
+  inQuotaMinutes: number;
+  overageMinutes: number;
+  inQuotaPrice: number;      // 配额内价格
+  overagePrice: number;       // 超额价格
   totalPrice: number;
   estimatedCost: number;
-  remainingMinutes: number;
 } {
   const audioMinutes = calculateAudioDuration(textLength);
-  const pricePerMinute = AUDIO_BILLING_CONFIG.pricePerMinute[quality] || 1.0;
-  const totalPrice = Math.round(audioMinutes * pricePerMinute * 100) / 100;
+  const monthlyMinutes = AUDIO_BILLING_CONFIG.monthlyMinutes[memberLevel] || 10;
+  const overagePricePerMinute = AUDIO_BILLING_CONFIG.overagePrice[memberLevel];
+  
+  // 计算配额内和超额分钟数
+  const remainingQuota = Math.max(0, monthlyMinutes - usedMinutes);
+  const inQuotaMinutes = Math.min(audioMinutes, remainingQuota);
+  const overageMinutes = Math.max(0, audioMinutes - inQuotaMinutes);
+  
+  // 配额内价格(包月批发价)
+  const inQuotaPrice = inQuotaMinutes * AUDIO_BILLING_CONFIG.pricing.monthly.basePricePerMinute;
+  
+  // 超额价格(按量零售价)
+  const overagePrice = overageMinutes > 0 && overagePricePerMinute !== null
+    ? overageMinutes * overagePricePerMinute
+    : 0;
+  
+  const totalPrice = Math.round((inQuotaPrice + overagePrice) * 100) / 100;
   
   return {
     textLength,
     audioMinutes,
-    pricePerMinute,
+    inQuotaMinutes,
+    overageMinutes,
+    inQuotaPrice: Math.round(inQuotaPrice * 100) / 100,
+    overagePrice: Math.round(overagePrice * 100) / 100,
     totalPrice,
-    estimatedCost: AUDIO_BILLING_CONFIG.costPerMinute[quality] * audioMinutes,
-    remainingMinutes: 0  // 需要查询用户余额才能确定
+    estimatedCost: audioMinutes * AUDIO_BILLING_CONFIG.costPerMinute
   };
 }
 
@@ -592,7 +656,9 @@ export async function getUserAudioBalance(userId: number) {
   }
   
   const memberLevel = user.memberLevel as MemberLevel;
-  const monthlyMinutes = AUDIO_BILLING_CONFIG.monthlyMinutes[memberLevel] || 30;
+  const monthlyMinutes = AUDIO_BILLING_CONFIG.monthlyMinutes[memberLevel] || 10;
+  const overageEnabled = AUDIO_BILLING_CONFIG.overagePrice[memberLevel] !== null;
+  const overagePrice = AUDIO_BILLING_CONFIG.overagePrice[memberLevel];
   
   // 检查是否需要重置月度配额
   const now = new Date();
@@ -618,10 +684,12 @@ export async function getUserAudioBalance(userId: number) {
   }
   
   return {
+    memberLevel,
     totalMinutes,
     usedMinutes,
     remainingMinutes: totalMinutes - usedMinutes,
-    isUnlimited: memberLevel >= 3,  // 旗舰版及以上无限制
+    overageEnabled,
+    overagePrice: overagePrice || 0,
     resetDate: user.subscriptionResetDate
   };
 }
@@ -629,12 +697,11 @@ export async function getUserAudioBalance(userId: number) {
 // 检查音频生成配额
 export async function checkAudioQuota(
   userId: number,
-  textLength: number,
-  quality: 'standard' | 'high' | 'lossless' = 'high'
+  textLength: number
 ) {
   const audioMinutes = calculateAudioDuration(textLength);
   const balance = await getUserAudioBalance(userId);
-  const maxMinutes = AUDIO_BILLING_CONFIG.maxMinutesPerGeneration[balance.isUnlimited ? 3 : 0] || 2;
+  const maxMinutes = AUDIO_BILLING_CONFIG.maxMinutesPerGeneration[balance.memberLevel] || 2;
   
   // 检查单次限制
   if (audioMinutes > maxMinutes) {
@@ -647,13 +714,14 @@ export async function checkAudioQuota(
   }
   
   // 检查月度配额
-  if (!balance.isUnlimited && balance.remainingMinutes < audioMinutes) {
+  if (balance.remainingMinutes < audioMinutes && !balance.overageEnabled) {
     return {
       allowed: false,
-      reason: `音频时长不足,需要${audioMinutes}分钟,剩余${balance.remainingMinutes}分钟`,
+      reason: `音频时长不足,本月配额已用完`,
       audioMinutes,
       remainingMinutes: balance.remainingMinutes,
-      totalMinutes: balance.totalMinutes
+      totalMinutes: balance.totalMinutes,
+      overageEnabled: false
     };
   }
   
@@ -661,8 +729,12 @@ export async function checkAudioQuota(
     allowed: true,
     reason: null,
     audioMinutes,
-    remainingMinutes: balance.remainingMinutes - audioMinutes,
-    totalMinutes: balance.totalMinutes
+    inQuotaMinutes: Math.min(audioMinutes, balance.remainingMinutes),
+    overageMinutes: Math.max(0, audioMinutes - balance.remainingMinutes),
+    remainingMinutes: balance.remainingMinutes,
+    totalMinutes: balance.totalMinutes,
+    overageEnabled: balance.overageEnabled,
+    overagePrice: balance.overagePrice
   };
 }
 
@@ -670,11 +742,11 @@ export async function checkAudioQuota(
 export async function consumeAudioMinutes(
   userId: number,
   textLength: number,
-  quality: 'standard' | 'high' | 'lossless' = 'high',
   description?: string
 ) {
   const audioMinutes = calculateAudioDuration(textLength);
-  const cost = calculateAudioCost(textLength, quality);
+  const balance = await getUserAudioBalance(userId);
+  const cost = calculateAudioCost(textLength, balance.memberLevel, balance.usedMinutes);
   
   // 更新用户已使用时长
   await prisma.user.update({
@@ -691,7 +763,7 @@ export async function consumeAudioMinutes(
       type: 'audio_generation',
       amount: audioMinutes,
       contentLength: textLength,
-      description: description || `${audioMinutes}分钟${quality}音质音频`
+      description: description || `${audioMinutes}分钟音频`
     }
   });
   
@@ -699,34 +771,42 @@ export async function consumeAudioMinutes(
     usageId: usage.id,
     audioMinutes,
     textLength,
-    quality,
-    cost: cost.totalPrice
+    inQuotaMinutes: cost.inQuotaMinutes,
+    overageMinutes: cost.overageMinutes,
+    inQuotaPrice: cost.inQuotaPrice,
+    overagePrice: cost.overagePrice,
+    totalPrice: cost.totalPrice
   };
 }
 
 // 获取音频生成预估(用于UI展示)
 export async function getAudioEstimate(
   userId: number,
-  textLength: number,
-  quality: 'standard' | 'high' | 'lossless' = 'high'
+  textLength: number
 ) {
-  const cost = calculateAudioCost(textLength, quality);
-  const quota = await checkAudioQuota(userId, textLength, quality);
   const balance = await getUserAudioBalance(userId);
+  const cost = calculateAudioCost(textLength, balance.memberLevel, balance.usedMinutes);
+  const quota = await checkAudioQuota(userId, textLength);
   
   return {
     // 预估信息
     textLength,
     audioMinutes: cost.audioMinutes,
-    pricePerMinute: cost.pricePerMinute,
+    inQuotaMinutes: cost.inQuotaMinutes,
+    overageMinutes: cost.overageMinutes,
+    inQuotaPrice: cost.inQuotaPrice,
+    overagePrice: cost.overagePrice,
     estimatedPrice: cost.totalPrice,
     estimatedCost: cost.estimatedCost,
     
     // 用户配额
-    remainingMinutes: quota.allowed 
-      ? quota.remainingMinutes 
-      : balance.remainingMinutes,
+    remainingMinutes: balance.remainingMinutes,
     totalMinutes: balance.totalMinutes,
+    usedMinutes: balance.usedMinutes,
+    
+    // 计费策略
+    overageEnabled: balance.overageEnabled,
+    overagePrice: balance.overagePrice,
     
     // 是否允许生成
     canGenerate: quota.allowed,
@@ -734,7 +814,9 @@ export async function getAudioEstimate(
     
     // 显示文本
     displayText: quota.allowed
-      ? `预计${cost.audioMinutes}分钟音频,约¥${cost.totalPrice}`
+      ? cost.overageMinutes > 0
+        ? `预计${cost.audioMinutes}分钟(配额${cost.inQuotaMinutes}分钟+超出${cost.overageMinutes}分钟),约¥${cost.totalPrice}`
+        : `预计${cost.audioMinutes}分钟,约¥${cost.totalPrice}`
       : quota.reason
   };
 }