Files
mqsrv/src/routes/vip.ts
T
2026-05-09 00:52:04 +08:00

112 lines
2.9 KiB
TypeScript

import { Router, Request, Response } from 'express';
import { PrismaClient } from '@prisma/client';
import { z } from 'zod';
import { authMiddleware } from '../middleware/auth';
const router = Router();
const prisma = new PrismaClient();
// ============================================
// VIP 卡密激活
// ============================================
const activateSchema = z.object({
cardKey: z.string().regex(/^VIP\d+-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{4}$/),
});
router.post('/activate-vip', authMiddleware, async (req: Request, res: Response) => {
try {
const body = activateSchema.parse(req.body);
// 查找卡密
const card = await prisma.vipCard.findUnique({
where: { cardKey: body.cardKey },
});
if (!card) {
return res.status(400).json({
success: false,
message: '卡密不存在',
});
}
if (card.status !== 'UNUSED') {
return res.status(400).json({
success: false,
message: '卡密已被使用或已失效',
});
}
// 获取用户当前 VIP 状态
const user = await prisma.user.findUnique({
where: { id: req.user!.userId },
select: { isVip: true, vipExpireAt: true, vipLevel: true },
});
if (!user) {
return res.status(404).json({
success: false,
message: '用户不存在',
});
}
// 计算新的 VIP 过期时间
let newExpireAt: Date;
if (user.vipExpireAt && user.isVip && new Date() < user.vipExpireAt) {
// 已是 VIP,延长时间
newExpireAt = new Date(user.vipExpireAt.getTime() + card.days * 24 * 60 * 60 * 1000);
} else {
// 非 VIP,从现在开始计算
newExpireAt = new Date(Date.now() + card.days * 24 * 60 * 60 * 1000);
}
// 更新用户 VIP 状态
const updatedUser = await prisma.user.update({
where: { id: req.user!.userId },
data: {
isVip: true,
vipExpireAt: newExpireAt,
vipLevel: Math.max(user.vipLevel, 1),
},
});
// 更新卡密状态
await prisma.vipCard.update({
where: { id: card.id },
data: {
status: 'USED',
usedBy: req.user!.userId,
usedAt: new Date(),
},
});
// 记录日志
await prisma.userLog.create({
data: {
userId: req.user!.userId,
action: 'VIP_ACTIVATE',
targetId: card.id,
ipAddress: req.ip,
},
});
res.json({
success: true,
isVip: true,
vipExpireAt: newExpireAt,
vipLevel: updatedUser.vipLevel,
message: `激活成功,VIP 有效期延长 ${card.days} 天`,
});
} catch (error) {
if (error instanceof z.ZodError) {
return res.status(400).json({
success: false,
message: '卡密格式无效',
});
}
console.error('Activate VIP error:', error);
res.status(500).json({ success: false, message: '激活失败' });
}
});
export default router;