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 | import { Context, Next } from 'koa'; import { prisma } from '../models'; import { QuotaExceededError, ForbiddenError } from './errorHandler'; import { MEMBER_QUOTA, MemberLevel } from '../types'; // 检查使用次数限制 export async function usageLimitMiddleware(ctx: Context, next: Next): Promise<void> { const userId = ctx.state.user?.userId; // 测试模式:无需登录即可使用 if (!userId) { ctx.state.userQuota = { dailyLimit: -1, wordLimit: -1 }; await next(); return; } const user = await prisma.user.findUnique({ where: { id: parseInt(userId) } }); if (!user) { throw new ForbiddenError('用户不存在'); } const today = new Date().toISOString().slice(0, 10); const memberLevel = user.memberLevel; const quota = MEMBER_QUOTA[memberLevel as MemberLevel]; // 重置每日使用次数 if (user.lastUsageDate !== today) { await prisma.user.update({ where: { id: parseInt(userId) }, data: { dailyUsage: 0, lastUsageDate: today, }, }); user.dailyUsage = 0; user.lastUsageDate = today; } // 检查次数限制 (-1 表示无限制) if (quota.dailyLimit !== -1 && user.dailyUsage >= quota.dailyLimit) { throw new QuotaExceededError(`今日使用次数已达上限(${quota.dailyLimit}次),请升级会员`); } // 将用户信息和配额存入 state ctx.state.userQuota = quota; ctx.state.userInfo = user; await next(); } // 检查字数限制 export function checkWordLimit(wordCount: number): (ctx: Context, next: Next) => Promise<void> { return async (ctx: Context, next: Next) => { const quota = ctx.state.userQuota; if (!quota) { throw new ForbiddenError('请先检查使用限制'); } // -1 表示无限制 if (quota.wordLimit !== -1 && wordCount > quota.wordLimit) { throw new QuotaExceededError(`文本字数超出限制(${quota.wordLimit}字),请升级会员或缩短文本`); } await next(); }; } |