아이템 관리 자산 분류와 기본 필터를 정리한다
This commit is contained in:
@@ -16,7 +16,15 @@ const props = defineProps({
|
||||
<div v-if="!props.customItems.length" class="hint">조건에 맞는 관리 대상 아이템이 없어요.</div>
|
||||
<div v-else class="customItemGrid">
|
||||
<button v-for="item in props.customItems" :key="item.id" type="button" class="customItemCard" @click="props.openCustomItemModal(item)">
|
||||
<span class="customItemCard__badge" :class="{ 'customItemCard__badge--template': item.sourceType === 'template' }">{{ item.sourceLabel }}</span>
|
||||
<span
|
||||
class="customItemCard__badge"
|
||||
:class="{
|
||||
'customItemCard__badge--template': item.sourceType === 'template',
|
||||
'customItemCard__badge--asset': item.sourceType === 'asset',
|
||||
}"
|
||||
>
|
||||
{{ item.sourceLabel }}
|
||||
</span>
|
||||
<img class="customItemCard__image" :src="toApiUrl(item.src)" :alt="item.label" />
|
||||
<div class="customItemCard__title" :title="item.label">{{ item.label }}</div>
|
||||
</button>
|
||||
|
||||
@@ -119,9 +119,19 @@ export function useAdminCustomItems({
|
||||
closeCustomItemDeleteModal()
|
||||
closeCustomItemModal()
|
||||
await refreshCustomItems()
|
||||
success.value = item.sourceType === 'template' ? '선택한 템플릿 아이템을 제거했어요.' : '사용자 업로드 이미지를 삭제했어요.'
|
||||
success.value =
|
||||
item.sourceType === 'template'
|
||||
? '선택한 템플릿 아이템을 제거했어요.'
|
||||
: item.sourceType === 'asset'
|
||||
? '선택한 이미지 자산을 삭제했어요.'
|
||||
: '사용자 업로드 이미지를 삭제했어요.'
|
||||
} catch (e) {
|
||||
error.value = item.sourceType === 'template' ? '템플릿 아이템 제거에 실패했어요.' : '사용자 업로드 이미지 삭제에 실패했어요.'
|
||||
error.value =
|
||||
item.sourceType === 'template'
|
||||
? '템플릿 아이템 제거에 실패했어요.'
|
||||
: item.sourceType === 'asset'
|
||||
? '이미지 자산 삭제에 실패했어요.'
|
||||
: '사용자 업로드 이미지 삭제에 실패했어요.'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ const customItemQuery = ref('')
|
||||
const customItemPage = ref(1)
|
||||
const customItemLimit = ref(50)
|
||||
const customItemTotal = ref(0)
|
||||
const customItemFilter = ref('all')
|
||||
const customItemFilter = ref('library')
|
||||
const customItemModalTargetTemplateId = ref('')
|
||||
|
||||
const adminTierLists = ref([])
|
||||
@@ -242,7 +242,12 @@ const activeTabDescription = computed(() => {
|
||||
})
|
||||
const adminOverviewStats = computed(() => {
|
||||
const pendingRequests = templateRequests.value.length
|
||||
const orphanItems = customItems.value.filter((item) => item.usageCount === 0).length
|
||||
const orphanItems = customItems.value.filter(
|
||||
(item) =>
|
||||
item.sourceType === 'user' &&
|
||||
Number(item.usageCount || 0) === 0 &&
|
||||
!(Array.isArray(item.linkedTemplates) && item.linkedTemplates.length > 0)
|
||||
).length
|
||||
const adminCount = users.value.filter((user) => user.isAdmin).length
|
||||
|
||||
if (activeTab.value === 'featured') {
|
||||
@@ -264,8 +269,9 @@ const adminOverviewStats = computed(() => {
|
||||
if (activeTab.value === 'items') {
|
||||
return [
|
||||
{ label: '검색 결과', value: `${customItemTotal.value}` },
|
||||
{ label: '미사용', value: `${orphanItems}` },
|
||||
{ label: '미사용 사용자 아이템', value: `${orphanItems}` },
|
||||
{ label: '템플릿 아이템', value: `${customItems.value.filter((item) => item.sourceType === 'template').length}` },
|
||||
{ label: '이미지 자산', value: `${customItems.value.filter((item) => item.sourceType === 'asset').length}` },
|
||||
]
|
||||
}
|
||||
if (activeTab.value === 'tierlists') {
|
||||
@@ -490,7 +496,7 @@ watch(
|
||||
|
||||
if (tab === 'items') {
|
||||
customItemQuery.value = ''
|
||||
customItemFilter.value = 'all'
|
||||
customItemFilter.value = 'library'
|
||||
customItemPage.value = 1
|
||||
await refreshCustomItems()
|
||||
return
|
||||
@@ -599,10 +605,11 @@ function formatImageJobStatus(status) {
|
||||
|
||||
function customItemDeleteImpactText(item) {
|
||||
if (!item) return ''
|
||||
if (item.sourceType === 'asset' || item.isAssetLibraryItem) {
|
||||
return `"${item.label}" ${item.sourceLabel || '이미지 자산'} 항목을 정리할까요? 라이브러리 항목만 제거되고, 같은 이미지를 쓰는 다른 참조는 그대로 유지됩니다.`
|
||||
}
|
||||
if (item.sourceType === 'template') {
|
||||
return item.isAssetLibraryItem
|
||||
? `"${item.label}" 보관 자산 항목을 정리할까요? 라이브러리 항목만 제거되고, 같은 이미지를 쓰는 다른 참조는 그대로 유지됩니다.`
|
||||
: `"${item.label}" 템플릿 항목을 정리할까요? 연결된 템플릿과 같은 주제의 저장된 티어표에서 이 항목이 함께 제거될 수 있어요.`
|
||||
return `"${item.label}" 템플릿 항목을 정리할까요? 연결된 템플릿과 같은 주제의 저장된 티어표에서 이 항목이 함께 제거될 수 있어요.`
|
||||
}
|
||||
|
||||
return `"${item.label}" 사용자 업로드 이미지를 삭제할까요? 현재 항목만 정리됩니다.`
|
||||
@@ -747,7 +754,7 @@ function setTab(tab) {
|
||||
}
|
||||
if (tab === 'items') {
|
||||
customItemQuery.value = ''
|
||||
customItemFilter.value = 'all'
|
||||
customItemFilter.value = 'library'
|
||||
customItemPage.value = 1
|
||||
refreshCustomItems()
|
||||
}
|
||||
@@ -1389,7 +1396,7 @@ function buildModalItemFromTierListItem(item, tierList) {
|
||||
id,
|
||||
label: item?.label || matchedItem?.label || '이름 없음',
|
||||
src: item?.src || matchedItem?.src || '',
|
||||
sourceType: matchedItem?.sourceType || (String(id).startsWith('asset:') ? 'template' : 'user'),
|
||||
sourceType: matchedItem?.sourceType || (String(id).startsWith('asset:') ? 'asset' : 'user'),
|
||||
sourceLabel: matchedItem?.sourceLabel || '티어표 추가 아이템',
|
||||
ownerName: matchedItem?.ownerName || tierListAuthorDisplayName(tierList),
|
||||
linkedTemplates: Array.isArray(matchedItem?.linkedTemplates) ? matchedItem.linkedTemplates : [],
|
||||
@@ -2289,12 +2296,13 @@ function openUserProfile(user) {
|
||||
<option :value="200">200개씩 보기</option>
|
||||
</select>
|
||||
<select :value="customItemFilter" class="select" @change="changeCustomItemFilter($event.target.value)">
|
||||
<option value="library">아이템만 (템플릿+사용자)</option>
|
||||
<option value="all">전체 이미지</option>
|
||||
<option value="user">사용자 업로드</option>
|
||||
<option value="template">템플릿 사용 이미지</option>
|
||||
<option value="asset">관리자 보관 자산</option>
|
||||
<option value="template">관리자 템플릿 아이템</option>
|
||||
<option value="asset">썸네일·프로필 이미지</option>
|
||||
<option value="unused-user">미사용 사용자 업로드</option>
|
||||
<option value="unused-admin">미사용 관리자 자산</option>
|
||||
<option value="unused-admin">미사용 썸네일·프로필 이미지</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="adminSidebar__actions">
|
||||
@@ -3480,6 +3488,9 @@ function openUserProfile(user) {
|
||||
.adminUiScope .customItemCard__badge--template {
|
||||
background: rgba(96, 165, 250, 0.18);
|
||||
}
|
||||
.adminUiScope .customItemCard__badge--asset {
|
||||
background: rgba(251, 191, 36, 0.18);
|
||||
}
|
||||
.adminUiScope .customItemCard:hover {
|
||||
border-color: rgba(126, 162, 255, 0.42);
|
||||
background: rgba(255, 255, 255, 0.06);
|
||||
|
||||
Reference in New Issue
Block a user