chore: mqsrv backend

This commit is contained in:
Chen Gu
2026-05-09 00:52:04 +08:00
commit b84f111e8f
21 changed files with 4593 additions and 0 deletions

167
src/routes/favorites.ts Normal file
View File

@@ -0,0 +1,167 @@
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();
router.use(authMiddleware);
const TARGET_TYPES = ['SCHEME', 'SCHEME_AOB', 'FILTER'] as const;
// ============================================
// 获取收藏列表
// ============================================
router.get('/', async (req: Request, res: Response) => {
try {
const { type, page = 1, limit = 20 } = req.query;
const skip = (Number(page) - 1) * Number(limit);
const where: any = { userId: req.user!.userId };
if (type && TARGET_TYPES.includes(type as any)) {
where.targetType = type;
}
const favorites = await prisma.favorite.findMany({
where,
orderBy: { createdAt: 'desc' },
skip,
take: Number(limit),
});
res.json({ success: true, data: favorites });
} catch (error) {
console.error('Get favorites error:', error);
res.status(500).json({ success: false, message: '获取失败' });
}
});
// ============================================
// 添加收藏
// ============================================
const addFavoriteSchema = z.object({
targetType: z.enum(TARGET_TYPES),
targetId: z.string().uuid(),
});
router.post('/', async (req: Request, res: Response) => {
try {
const body = addFavoriteSchema.parse(req.body);
// 检查是否已收藏
const existing = await prisma.favorite.findFirst({
where: {
userId: req.user!.userId,
targetType: body.targetType,
targetId: body.targetId,
},
});
if (existing) {
return res.status(400).json({ success: false, message: '已收藏' });
}
// 验证目标是否存在
let targetExists = false;
if (body.targetType === 'SCHEME') {
targetExists = !!(await prisma.scheme.findFirst({
where: { id: body.targetId, status: 'PUBLISHED' },
}));
} else if (body.targetType === 'SCHEME_AOB') {
targetExists = !!(await prisma.schemeAob.findFirst({
where: { id: body.targetId, status: 'PUBLISHED' },
}));
} else if (body.targetType === 'FILTER') {
targetExists = !!(await prisma.filterShare.findFirst({
where: { id: body.targetId, status: 'PUBLISHED' },
}));
}
if (!targetExists) {
return res.status(404).json({ success: false, message: '目标不存在' });
}
// 创建收藏
await prisma.favorite.create({
data: {
userId: req.user!.userId,
targetType: body.targetType,
targetId: body.targetId,
},
});
// 更新用户收藏数
await prisma.user.update({
where: { id: req.user!.userId },
data: { favoritesCount: { increment: 1 } },
});
res.json({ success: true, message: '收藏成功' });
} catch (error) {
console.error('Add favorite error:', error);
res.status(500).json({ success: false, message: '收藏失败' });
}
});
// ============================================
// 取消收藏
// ============================================
router.delete('/:id', async (req: Request, res: Response) => {
try {
const { id } = req.params;
const favorite = await prisma.favorite.findUnique({
where: { id },
});
if (!favorite || favorite.userId !== req.user!.userId) {
return res.status(404).json({ success: false, message: '收藏不存在' });
}
await prisma.favorite.delete({ where: { id } });
// 更新用户收藏数
await prisma.user.update({
where: { id: req.user!.userId },
data: { favoritesCount: { decrement: 1 } },
});
res.json({ success: true, message: '已取消收藏' });
} catch (error) {
console.error('Remove favorite error:', error);
res.status(500).json({ success: false, message: '取消收藏失败' });
}
});
// ============================================
// 检查是否已收藏
// ============================================
router.get('/check', async (req: Request, res: Response) => {
try {
const { targetType, targetId } = req.query;
if (!targetType || !targetId) {
return res.status(400).json({ success: false, message: '参数缺失' });
}
const favorite = await prisma.favorite.findFirst({
where: {
userId: req.user!.userId,
targetType: String(targetType),
targetId: String(targetId),
},
});
res.json({
success: true,
isFavorited: !!favorite,
favoriteId: favorite?.id || null,
});
} catch (error) {
console.error('Check favorite error:', error);
res.status(500).json({ success: false, message: '检查失败' });
}
});
export default router;