feat: add map-password API with DB model and admin endpoint
This commit is contained in:
1252
origet/ test_output_202605240119.json
Normal file
1252
origet/ test_output_202605240119.json
Normal file
File diff suppressed because it is too large
Load Diff
BIN
origet/__pycache__/api_spec.cpython-313.pyc
Normal file
BIN
origet/__pycache__/api_spec.cpython-313.pyc
Normal file
Binary file not shown.
BIN
origet/__pycache__/client.cpython-312.pyc
Normal file
BIN
origet/__pycache__/client.cpython-312.pyc
Normal file
Binary file not shown.
BIN
origet/__pycache__/client.cpython-313.pyc
Normal file
BIN
origet/__pycache__/client.cpython-313.pyc
Normal file
Binary file not shown.
BIN
origet/__pycache__/decrypt.cpython-313.pyc
Normal file
BIN
origet/__pycache__/decrypt.cpython-313.pyc
Normal file
Binary file not shown.
@@ -280,3 +280,31 @@ model DeviceBinding {
|
|||||||
@@unique([userId, installId])
|
@@unique([userId, installId])
|
||||||
@@map("device_bindings")
|
@@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")
|
||||||
|
}
|
||||||
|
|||||||
58
src/index.ts
58
src/index.ts
@@ -158,9 +158,30 @@ app.get('/api/software-version-ad', (req, res) => {
|
|||||||
res.json({ success: true, data: { items: [] } });
|
res.json({ success: true, data: { items: [] } });
|
||||||
});
|
});
|
||||||
|
|
||||||
// 游戏地图密码缓存
|
// 游戏地图密码缓存(对齐 maqt.top 格式)
|
||||||
app.get('/api/game/map-password/cached', (req, res) => {
|
app.get('/api/game/map-password/cached', async (_req, res) => {
|
||||||
res.json({ success: true, data: [] });
|
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 });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// ============================================
|
// ============================================
|
||||||
// 错误处理
|
// 错误处理
|
||||||
// ============================================
|
// ============================================
|
||||||
|
|||||||
Reference in New Issue
Block a user