chore: mqsrv backend

This commit is contained in:
Chen Gu
2026-05-09 00:52:04 +08:00
commit 606137e030
2165 changed files with 904507 additions and 0 deletions

212
src/index.ts Normal file
View File

@@ -0,0 +1,212 @@
import express, { Request, Response } from 'express';
import cors from 'cors';
import helmet from 'helmet';
import rateLimit from 'express-rate-limit';
import dotenv from 'dotenv';
dotenv.config();
import authRoutes from './routes/auth';
import userRoutes from './routes/user';
import schemeRoutes from './routes/schemes';
import schemeAobRoutes from './routes/schemesAob';
import filterRoutes from './routes/filters';
import vipRoutes from './routes/vip';
import favoriteRoutes from './routes/favorites';
const app = express();
const PORT = process.env.PORT || 3001;
// ============================================
// 中间件
// ============================================
// 安全头 - 开发模式禁用 CSP
app.use(helmet({
contentSecurityPolicy: false,
crossOriginEmbedderPolicy: false,
}));
// CORS
app.use(cors({
origin: true, // 允许所有来源(开发模式)
credentials: true,
}));
// JSON 解析
app.use(express.json({ limit: '10mb' }));
app.use(express.urlencoded({ extended: true }));
// 速率限制
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 分钟
max: 100, // 每个 IP 最多 100 次请求
message: { success: false, message: '请求过于频繁,请稍后再试' },
});
app.use('/api/', limiter);
// 登录接口更严格的限制
const loginLimiter = rateLimit({
windowMs: 15 * 60 * 1000,
max: 10,
message: { success: false, message: '登录尝试过于频繁,请稍后再试' },
});
app.use('/api/login', loginLimiter);
app.use('/api/register', loginLimiter);
// ============================================
// 路由
// ============================================
app.get('/api/activity/ping', (req, res) => {
res.json({ success: true, message: 'pong', timestamp: Date.now() });
});
app.use('/api', authRoutes);
app.use('/api/user', userRoutes);
app.use('/api/schemes', schemeRoutes);
app.use('/api/schemes_aob', schemeAobRoutes);
app.use('/api/filter-shares', filterRoutes);
app.use('/api', vipRoutes);
// 收藏计数(放在 favorites 路由之前,避免 auth 中间件拦截)
app.get('/api/favorites/count', async (req: Request, res: Response) => {
try {
const { PrismaClient } = require('@prisma/client');
const prisma = new PrismaClient();
const count = await prisma.favorite.count();
res.json({ success: true, count });
} catch (e) {
res.json({ success: true, count: 0 });
}
});
app.use('/api/favorites', favoriteRoutes);
// ============================================
// 缺失的存根接口(防止前端 404
// ============================================
// 二维码
app.get('/api/qrcode/public/current', (req, res) => {
res.json({ success: true, data: { qrcode: null, url: '' } });
});
// 弹窗
app.get('/api/popups/', (req, res) => {
res.json({ success: true, data: [] });
});
// 售后教程弹窗
app.get('/api/aftersale-tutorial-popup', (req, res) => {
res.json({ success: true, data: { shown: false } });
});
// 软件版本广告空数据dock 无广告项)
app.get('/api/software-version-ad', (req, res) => {
res.json({ success: true, data: { items: [] } });
});
// 游戏地图密码缓存
app.get('/api/game/map-password/cached', (req, res) => {
res.json({ success: true, data: [] });
});
// 筛选分类
app.get('/api/filter-share/categories', (req, res) => {
res.json({ success: true, data: [] });
});
// ============================================
// 武器调谐窗 (weapon-tuner) 所需的 API
// ============================================
// 武器分类列表
app.get('/api/weapon-categories', (req, res) => {
const categories = [
{ category: 'AR', name: '突击步枪' },
{ category: 'SMG', name: '冲锋枪' },
{ category: 'SR', name: '狙击步枪' },
{ category: 'LMG', name: '轻机枪' },
{ category: 'SG', name: '霰弹枪' },
{ category: 'Pistol', name: '手枪' },
{ category: 'Launcher', name: '发射器' },
];
res.json({ success: true, data: categories });
});
// 武器列表(按分类筛选)
app.get('/api/weapons', (req, res) => {
res.json({ success: true, data: [] });
});
// 分类下的武器
app.get('/api/category/:code', (req, res) => {
res.json({ success: true, data: [] });
});
// 广告列表
app.get('/api/adverts/list', (req, res) => {
res.json({ success: true, data: [
{
id: 1,
title: '码枪堂2.0 新版发布',
description: '全新界面,更多功能,一键优化三角洲行动游戏体验!',
author: '码枪堂官方',
avatar: null,
image_url: '',
link_url: 'https://wwamt.lanzout.com/b00odpq4wb',
isAdvert: true,
isVip: true,
shareTime: new Date().toISOString(),
}
] });
});
// 广告点击
app.post('/api/adverts/:id/click', (req, res) => {
res.json({ success: true, message: 'ok' });
});
// 头像列表
app.get('/api/avatars', (req, res) => {
res.json({ success: true, data: [] });
});
// ============================================
// 错误处理
// ============================================
app.use((err: any, req: express.Request, res: express.Response, next: express.NextFunction) => {
console.error('Error:', err);
if (err.name === 'UnauthorizedError') {
return res.status(401).json({ success: false, message: '访问令牌无效', code: 'INVALID_TOKEN' });
}
if (err.name === 'ZodError') {
return res.status(400).json({ success: false, message: '参数验证失败', errors: err.errors });
}
res.status(500).json({ success: false, message: '服务器内部错误' });
});
// 404
app.use((req, res) => {
res.status(404).json({ success: false, message: '接口不存在' });
});
// ============================================
// 启动
// ============================================
app.listen(PORT, () => {
console.log(`🚀 码枪堂 API 运行在 http://localhost:${PORT}`);
console.log(`📋 可用接口:`);
console.log(` POST /api/login`);
console.log(` POST /api/register`);
console.log(` POST /api/activate-vip`);
console.log(` GET /api/session-status`);
console.log(` GET /api/vip-status`);
});
export default app;