릴리스: v1.3.70 관리자 티어표 필터와 관리 액션 보강
This commit is contained in:
@@ -1951,22 +1951,32 @@ function getAutoThumbnailSrc(groups = [], pool = []) {
|
||||
return fallbackItem?.src || ''
|
||||
}
|
||||
|
||||
async function listAdminTierLists({ queryText = '', page = 1, limit = 50, currentUserId = '' } = {}) {
|
||||
async function listAdminTierLists({ queryText = '', gameId = '', page = 1, limit = 50, currentUserId = '' } = {}) {
|
||||
const normalizedLimit = Math.min(Math.max(Number(limit) || 50, 1), 200)
|
||||
const normalizedPage = Math.max(Number(page) || 1, 1)
|
||||
const hasQuery = !!(queryText || '').trim()
|
||||
const hasGameId = !!(gameId || '').trim()
|
||||
const search = `%${(queryText || '').trim()}%`
|
||||
const whereClause = hasQuery
|
||||
? `
|
||||
WHERE
|
||||
t.title LIKE ?
|
||||
OR g.name LIKE ?
|
||||
OR g.id LIKE ?
|
||||
OR u.email LIKE ?
|
||||
OR u.nickname LIKE ?
|
||||
`
|
||||
: ''
|
||||
const params = hasQuery ? [search, search, search, search, search] : []
|
||||
const whereParts = []
|
||||
const params = []
|
||||
|
||||
if (hasGameId) {
|
||||
whereParts.push('t.game_id = ?')
|
||||
params.push((gameId || '').trim())
|
||||
}
|
||||
|
||||
if (hasQuery) {
|
||||
whereParts.push(`(
|
||||
t.title LIKE ?
|
||||
OR g.name LIKE ?
|
||||
OR g.id LIKE ?
|
||||
OR u.email LIKE ?
|
||||
OR u.nickname LIKE ?
|
||||
)`)
|
||||
params.push(search, search, search, search, search)
|
||||
}
|
||||
|
||||
const whereClause = whereParts.length ? `WHERE ${whereParts.join(' AND ')}` : ''
|
||||
|
||||
const rows = await query(
|
||||
`
|
||||
@@ -2288,6 +2298,18 @@ async function deleteTierList(id) {
|
||||
await query('DELETE FROM tierlists WHERE id = ?', [id])
|
||||
}
|
||||
|
||||
async function updateAdminTierListMeta({ id, title, description = '', isPublic }) {
|
||||
await query(
|
||||
`
|
||||
UPDATE tierlists
|
||||
SET title = ?, description = ?, is_public = ?, updated_at = ?
|
||||
WHERE id = ?
|
||||
`,
|
||||
[title, description || '', isPublic ? 1 : 0, now(), id]
|
||||
)
|
||||
return findTierListById(id)
|
||||
}
|
||||
|
||||
async function findCustomItemsByIds(ids) {
|
||||
if (!ids.length) return []
|
||||
const placeholders = ids.map(() => '?').join(', ')
|
||||
@@ -2454,6 +2476,7 @@ module.exports = {
|
||||
listAdminTierLists,
|
||||
summarizeAdminTierLists,
|
||||
findTierListById,
|
||||
updateAdminTierListMeta,
|
||||
favoriteTierList,
|
||||
unfavoriteTierList,
|
||||
favoriteGame,
|
||||
|
||||
@@ -22,6 +22,7 @@ const {
|
||||
updateImageAssetLabel,
|
||||
deleteGameItem,
|
||||
deleteGame,
|
||||
deleteTierList,
|
||||
updateGameDisplayOrder,
|
||||
listCustomItems,
|
||||
findCustomItemById,
|
||||
@@ -33,6 +34,7 @@ const {
|
||||
listAdminTierLists,
|
||||
summarizeAdminTierLists,
|
||||
findTierListById,
|
||||
updateAdminTierListMeta,
|
||||
listAdminTemplateRequests,
|
||||
findTemplateRequestById,
|
||||
updateTemplateRequestStatus,
|
||||
@@ -296,6 +298,7 @@ router.get('/custom-items', requireAdmin, async (req, res) => {
|
||||
router.get('/tierlists', requireAdmin, async (req, res) => {
|
||||
const schema = z.object({
|
||||
q: z.string().trim().max(120).optional().default(''),
|
||||
gameId: z.string().trim().max(120).optional().default(''),
|
||||
page: z.coerce.number().int().min(1).optional().default(1),
|
||||
limit: z.coerce.number().int().min(1).max(200).optional().default(50),
|
||||
})
|
||||
@@ -304,6 +307,7 @@ router.get('/tierlists', requireAdmin, async (req, res) => {
|
||||
|
||||
const result = await listAdminTierLists({
|
||||
queryText: parsed.data.q,
|
||||
gameId: parsed.data.gameId,
|
||||
page: parsed.data.page,
|
||||
limit: parsed.data.limit,
|
||||
currentUserId: req.session?.userId || '',
|
||||
@@ -693,6 +697,34 @@ router.post('/tierlists/:tierListId/create-game-template', requireAdmin, async (
|
||||
res.json(result)
|
||||
})
|
||||
|
||||
router.patch('/tierlists/:tierListId', requireAdmin, async (req, res) => {
|
||||
const schema = z.object({
|
||||
title: z.string().trim().min(1).max(120),
|
||||
description: z.string().max(500).optional().default(''),
|
||||
isPublic: z.boolean(),
|
||||
})
|
||||
const parsed = schema.safeParse(req.body)
|
||||
if (!parsed.success) return res.status(400).json({ error: 'bad_request' })
|
||||
|
||||
const tierList = await findTierListById(req.params.tierListId)
|
||||
if (!tierList) return res.status(404).json({ error: 'not_found' })
|
||||
|
||||
const updated = await updateAdminTierListMeta({
|
||||
id: tierList.id,
|
||||
title: parsed.data.title,
|
||||
description: parsed.data.description || '',
|
||||
isPublic: parsed.data.isPublic,
|
||||
})
|
||||
res.json({ tierList: updated })
|
||||
})
|
||||
|
||||
router.delete('/tierlists/:tierListId', requireAdmin, async (req, res) => {
|
||||
const tierList = await findTierListById(req.params.tierListId)
|
||||
if (!tierList) return res.status(404).json({ error: 'not_found' })
|
||||
await deleteTierList(tierList.id)
|
||||
res.json({ ok: true })
|
||||
})
|
||||
|
||||
router.post('/template-requests/:requestId/approve', requireAdmin, async (req, res) => {
|
||||
const templateRequest = await findTemplateRequestById(req.params.requestId)
|
||||
if (!templateRequest) return res.status(404).json({ error: 'not_found' })
|
||||
|
||||
Reference in New Issue
Block a user