chore: mqsrv backend
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
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;
|
||||
Reference in New Issue
Block a user