Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 | import Router from '@koa/router'; import { Context } from 'koa'; import * as SubscriptionService from './subscription.service'; import { BadRequestError } from '../../middleware/errorHandler'; import { authMiddleware } from '../../middleware/auth'; const router = new Router(); // 获取所有套餐列表 router.get('/plans', async (ctx: Context) => { const plans = await SubscriptionService.getPlans(); ctx.body = { code: 0, message: 'success', data: { plans } }; }); // 获取单个套餐详情 router.get('/plans/:id', async (ctx: Context) => { const planId = parseInt(ctx.params.id); const plan = await SubscriptionService.getPlanById(planId); ctx.body = { code: 0, message: 'success', data: { plan } }; }); // 获取用户订阅信息 router.get('/subscription', authMiddleware, async (ctx: Context) => { const userId = parseInt(ctx.state.user.userId); const subscription = await SubscriptionService.getUserSubscription(userId); ctx.body = { code: 0, message: 'success', data: { subscription } }; }); // 获取用户Token余额 router.get('/balance', authMiddleware, async (ctx: Context) => { const userId = parseInt(ctx.state.user.userId); const balance = await SubscriptionService.getUserTokenBalance(userId); ctx.body = { code: 0, message: 'success', data: balance }; }); // 获取Token使用记录 router.get('/usage', authMiddleware, async (ctx: Context) => { const userId = parseInt(ctx.state.user.userId); const { page = '1', pageSize = '20' } = ctx.query as { page?: string; pageSize?: string }; const result = await SubscriptionService.getTokenUsageList( userId, Number(page) || 1, Number(pageSize) || 20 ); ctx.body = { code: 0, message: 'success', data: result }; }); // 获取用户配额(兼容旧接口) router.get('/quota', authMiddleware, async (ctx: Context) => { const userId = parseInt(ctx.state.user.userId); const quota = await SubscriptionService.getUserQuota(userId); ctx.body = { code: 0, message: 'success', data: quota }; }); // 检查配额 router.post('/check-quota', authMiddleware, async (ctx: Context) => { const userId = parseInt(ctx.state.user.userId); const { tokens } = ctx.request.body as { tokens: number }; if (!tokens || tokens <= 0) { throw new BadRequestError('请提供正确的Token数量'); } const result = await SubscriptionService.checkQuota(userId, tokens); ctx.body = { code: 0, message: 'success', data: result }; }); // ============================================ // 书籍生成配额相关API // ============================================ // 获取书籍规模预估字数 router.get('/book-scale-estimate', async (ctx: Context) => { const { scale } = ctx.query as { scale?: string }; const result = SubscriptionService.estimateBookWords(scale || '1000'); ctx.body = { code: 0, message: 'success', data: { ...result, audioMinutes: SubscriptionService.estimateAudioMinutesFromWords(result.avg) } }; }); // 检查书籍生成配额(生成前预估) router.get('/book-generation-quota', authMiddleware, async (ctx: Context) => { const userId = parseInt(ctx.state.user.userId); const { scale } = ctx.query as { scale?: string }; if (!scale) { throw new BadRequestError('请提供书籍规模'); } const result = await SubscriptionService.checkBookGenerationQuota(userId, scale); ctx.body = { code: 0, message: result.allowed ? '额度充足' : '额度不足', data: result }; }); // 检查当前额度是否足够生成指定字数(生成过程监控) router.post('/check-quota-words', authMiddleware, async (ctx: Context) => { const userId = parseInt(ctx.state.user.userId); const { wordCount } = ctx.request.body as { wordCount: number }; if (!wordCount || wordCount <= 0) { throw new BadRequestError('请提供正确的字数'); } const result = await SubscriptionService.checkQuotaForWords(userId, wordCount); ctx.body = { code: 0, message: 'success', data: result }; }); // 获取用户音频时长余额(新版) router.get('/audio-balance', authMiddleware, async (ctx: Context) => { const userId = parseInt(ctx.state.user.userId); const balance = await SubscriptionService.getUserAudioBalance(userId); ctx.body = { code: 0, message: 'success', data: balance }; }); // 获取音频生成预估 router.get('/audio-estimate', authMiddleware, async (ctx: Context) => { const userId = parseInt(ctx.state.user.userId); const { textLength } = ctx.query as { textLength?: string }; if (!textLength || isNaN(parseInt(textLength))) { throw new BadRequestError('请提供正确的文本长度'); } const estimate = await SubscriptionService.getAudioEstimate(userId, parseInt(textLength)); ctx.body = { code: 0, message: 'success', data: estimate }; }); export default router; |