관리자 아이템 필터와 미사용 분류 정리

This commit is contained in:
2026-04-03 13:40:08 +09:00
parent 426e7de177
commit 66408aaa1b
7 changed files with 51 additions and 22 deletions

View File

@@ -205,10 +205,17 @@ function getAssetLibrarySourceLabel(src) {
const normalizedSrc = String(src || '').trim()
if (normalizedSrc.includes('/uploads/assets/avatars/')) return '프로필 아바타'
if (normalizedSrc.includes('/uploads/assets/tierlists/')) return '티어표 썸네일'
if (normalizedSrc.includes('/uploads/assets/topics/')) return '템플릿 썸네일'
if (normalizedSrc.includes('/uploads/assets/topics/')) return '썸네일 이미지'
return '보관 자산'
}
function getAssetLibraryKind(src) {
const normalizedSrc = String(src || '').trim()
if (normalizedSrc.includes('/uploads/assets/avatars/')) return 'avatar'
if (normalizedSrc.includes('/uploads/assets/tierlists/') || normalizedSrc.includes('/uploads/assets/topics/')) return 'thumbnail'
return 'asset'
}
async function createPool() {
const rootConnection = await mysql.createConnection({
host: DB_HOST,
@@ -1845,7 +1852,7 @@ async function listCustomItems({ queryText = '', page = 1, limit = 50, filterMod
usageCount: usageMeta.usageMap.get(row.id) || 0,
linkedTemplates,
sourceType: 'user',
sourceLabel: '사용자 업로드',
sourceLabel: '사용자 아이템',
canDelete: true,
}
})
@@ -1867,6 +1874,7 @@ async function listCustomItems({ queryText = '', page = 1, limit = 50, filterMod
linkedTemplates: [],
sourceType: 'asset',
sourceLabel: getAssetLibrarySourceLabel(row.src),
assetKind: getAssetLibraryKind(row.src),
canDelete: true,
sourceTopicId: '',
sourceTopicName: '',
@@ -1884,7 +1892,7 @@ async function listCustomItems({ queryText = '', page = 1, limit = 50, filterMod
usageCount: (templateLinkedBySrc.get(row.src) || new Map()).size,
linkedTemplates: Array.from((templateLinkedBySrc.get(row.src) || new Map()).values()),
sourceType: 'template',
sourceLabel: '관리자 템플릿',
sourceLabel: '템플릿 아이템',
canDelete: true,
sourceTopicId: row.topic_id,
sourceTopicName: row.topic_name || row.topic_id,
@@ -1930,6 +1938,7 @@ async function listCustomItems({ queryText = '', page = 1, limit = 50, filterMod
label: entry.label,
sourceLabel: entry.sourceLabel,
sourceType: entry.sourceType,
assetKind: entry.assetKind || '',
ownerName: entry.ownerName,
createdAt: entry.createdAt,
sourceTopicId: entry.sourceTopicId || '',
@@ -1948,6 +1957,10 @@ async function listCustomItems({ queryText = '', page = 1, limit = 50, filterMod
return item.sourceType === 'template' && !item.isAssetLibraryItem
case 'asset':
return item.sourceType === 'asset' || !!item.isAssetLibraryItem
case 'thumbnail':
return item.sourceType === 'asset' && item.assetKind === 'thumbnail'
case 'avatar':
return item.sourceType === 'asset' && item.assetKind === 'avatar'
case 'library':
return item.sourceType === 'user' || (item.sourceType === 'template' && !item.isAssetLibraryItem)
case 'unused-user':

View File

@@ -332,7 +332,10 @@ router.get('/custom-items', requireAdmin, async (req, res) => {
q: 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),
filter: z.enum(['library', 'all', 'user', 'template', 'asset', 'unused-user', 'unused-admin']).optional().default('library'),
filter: z
.enum(['library', 'all', 'user', 'template', 'asset', 'thumbnail', 'avatar', 'unused-user', 'unused-admin'])
.optional()
.default('library'),
})
const parsed = schema.safeParse(req.query)
if (!parsed.success) return res.status(400).json({ error: 'bad_request' })