Compare commits

...

2 Commits

11 changed files with 1345 additions and 6 deletions

1
.gitignore vendored
View File

@@ -8,3 +8,4 @@ dist/
`n__pycache__/
test_output*.json
results_v*.json
`n__pycache__/`noriget/ test_output_*.json`noriget/results_v*.json`n*.pyc

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -280,3 +280,31 @@ model DeviceBinding {
@@unique([userId, installId])
@@map("device_bindings")
}
// ============================================
// 地图密码批次表
// ============================================
model MapPassword {
id String @id @default(uuid())
createdAt DateTime @default(now()) @map("created_at")
maps MapPasswordItem[]
@@map("map_passwords")
}
// ============================================
// 地图密码明细表
// ============================================
model MapPasswordItem {
id String @id @default(uuid())
batchId String @map("batch_id")
mapName String @map("map_name") @db.VarChar(50)
password String @db.VarChar(20)
location String @db.Text
image String @db.VarChar(500)
batch MapPassword @relation(fields: [batchId], references: [id], onDelete: Cascade)
@@map("map_password_items")
}

View File

@@ -158,9 +158,30 @@ 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: [] });
// 游戏地图密码缓存(对齐 maqt.top 格式)
app.get('/api/game/map-password/cached', async (_req, res) => {
try {
// 从 DB 取最新一批地图密码
const latest = await prisma.mapPassword.findFirst({
orderBy: { createdAt: 'desc' },
include: { maps: { select: { mapName: true, password: true, location: true, image: true } } },
});
if (latest) {
const d = new Date(latest.createdAt);
res.json({
success: true,
data: {
maps: latest.maps,
updateTime: `${String(d.getDate()).padStart(2,'0')}${String(d.getMonth()+1).padStart(2,'0')}`,
},
});
} else {
// 默认空数据
res.json({ success: true, data: { maps: [], updateTime: '' } });
}
} catch {
res.json({ success: true, data: { maps: [], updateTime: '' } });
}
});
// 筛选分类
@@ -360,6 +381,37 @@ app.post('/api/admin/set-vip', async (req, res) => {
}
});
// 管理员更新地图密码
app.post('/api/admin/map-passwords', async (req, res) => {
const secret = process.env.ADMIN_SECRET;
if (!secret || req.headers['x-admin-secret'] !== secret) {
return res.status(403).json({ success: false, message: '禁止访问' });
}
try {
const { maps } = req.body;
if (!Array.isArray(maps) || maps.length === 0) {
return res.status(400).json({ success: false, message: '缺少 maps 数组' });
}
const batch = await prisma.mapPassword.create({
data: {
maps: {
create: maps.map((m: any) => ({
mapName: m.mapName,
password: m.password,
location: m.location || '',
image: m.image || '',
})),
},
},
include: { maps: true },
});
res.json({ success: true, data: batch });
} catch (e: any) {
console.error('Admin map-password error:', e);
res.status(500).json({ success: false, message: '更新失败: ' + e.message });
}
});
// ============================================
// 错误处理
// ============================================

View File

@@ -16,7 +16,7 @@ function sourceToType(source?: string): string {
// 格式化方案卡片(对齐顶层 API
function formatScheme(s: any) {
return {
id: parseInt(s.id, 36) || String(s.id).split('-')[0] || s.id,
id: s.id,
user_id: s.userId,
description: s.description || '',
scheme_content: s.schemeContent || '',

View File

@@ -10,7 +10,7 @@ const router = Router();
function formatScheme(s: any) {
return {
id: parseInt(s.id, 36) || String(s.id).split('-')[0] || s.id,
id: s.id,
user_id: s.userId,
description: s.description || '',
scheme_content: s.schemeContent || '',
@@ -190,6 +190,9 @@ router.post('/', authMiddleware, async (req: Request, res: Response) => {
price: priceNum,
status: 'PUBLISHED',
},
include: {
user: { select: { id: true, username: true, avatar: true } },
},
});
await prisma.user.update({

View File

@@ -8,7 +8,7 @@ const router = Router();
function formatScheme(s: any) {
return {
id: parseInt(s.id, 36) || String(s.id).split('-')[0] || s.id,
id: s.id,
user_id: s.userId,
description: s.description || '',
scheme_content: s.schemeContent || '',
@@ -151,6 +151,9 @@ router.post('/', authMiddleware, async (req: Request, res: Response) => {
schemeContent: body.scheme,
status: 'PUBLISHED',
},
include: {
user: { select: { id: true, username: true, avatar: true } },
},
});
await prisma.user.update({