미디어 카테고리 관리 추가
This commit is contained in:
@@ -4,8 +4,10 @@ definePageMeta({
|
||||
})
|
||||
|
||||
const searchText = ref('')
|
||||
const categoryFilter = ref('')
|
||||
const editingUrl = ref('')
|
||||
const editingName = ref('')
|
||||
const editingCategory = ref('')
|
||||
const deletingUrl = ref('')
|
||||
const errorMessage = ref('')
|
||||
const selectedMediaUrl = ref('')
|
||||
@@ -16,19 +18,21 @@ const { data: mediaItems, refresh } = await useFetch('/admin/api/media', {
|
||||
|
||||
const selectedMedia = computed(() => mediaItems.value.find((item) => item.url === selectedMediaUrl.value) || null)
|
||||
|
||||
const mediaCategories = computed(() => [...new Set(mediaItems.value
|
||||
.map((item) => item.category)
|
||||
.filter(Boolean))]
|
||||
.sort((left, right) => left.localeCompare(right)))
|
||||
|
||||
const filteredMediaItems = computed(() => {
|
||||
const query = searchText.value.trim().toLowerCase()
|
||||
const category = categoryFilter.value
|
||||
|
||||
if (!query) {
|
||||
return mediaItems.value
|
||||
}
|
||||
|
||||
return mediaItems.value.filter((item) => [
|
||||
return mediaItems.value.filter((item) => (!category || item.category === category) && (!query || [
|
||||
item.name,
|
||||
item.url,
|
||||
item.category,
|
||||
...item.usage.map((usage) => usage.title)
|
||||
].some((value) => value.toLowerCase().includes(query)))
|
||||
].some((value) => value.toLowerCase().includes(query))))
|
||||
})
|
||||
|
||||
/**
|
||||
@@ -57,6 +61,7 @@ const openMediaDetail = (item) => {
|
||||
selectedMediaUrl.value = item.url
|
||||
editingUrl.value = item.url
|
||||
editingName.value = item.title
|
||||
editingCategory.value = item.category
|
||||
errorMessage.value = ''
|
||||
}
|
||||
|
||||
@@ -78,6 +83,27 @@ const cancelRename = () => {
|
||||
editingName.value = ''
|
||||
}
|
||||
|
||||
/**
|
||||
* 미디어 카테고리 저장
|
||||
* @returns {Promise<void>} 저장 결과
|
||||
*/
|
||||
const saveMediaCategory = async () => {
|
||||
errorMessage.value = ''
|
||||
|
||||
try {
|
||||
await $fetch('/admin/api/media', {
|
||||
method: 'PUT',
|
||||
body: {
|
||||
url: selectedMedia.value.url,
|
||||
category: editingCategory.value
|
||||
}
|
||||
})
|
||||
await refresh()
|
||||
} catch (error) {
|
||||
errorMessage.value = error?.data?.message || '카테고리를 저장하지 못했습니다.'
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 미디어 파일명 변경
|
||||
* @returns {Promise<void>}
|
||||
@@ -154,12 +180,20 @@ const deleteMedia = async (item) => {
|
||||
미디어
|
||||
</h1>
|
||||
</div>
|
||||
<input
|
||||
v-model="searchText"
|
||||
class="admin-media__search w-full rounded border border-line bg-white px-3 py-2 text-sm md:w-72"
|
||||
type="search"
|
||||
placeholder="파일명, 경로, 사용처 검색"
|
||||
>
|
||||
<div class="admin-media__filters flex w-full flex-wrap gap-2 md:w-auto">
|
||||
<select v-model="categoryFilter" class="admin-media__category-filter w-full rounded border border-line bg-white px-3 py-2 text-sm md:w-44">
|
||||
<option value="">전체 카테고리</option>
|
||||
<option v-for="category in mediaCategories" :key="category" :value="category">
|
||||
{{ category }}
|
||||
</option>
|
||||
</select>
|
||||
<input
|
||||
v-model="searchText"
|
||||
class="admin-media__search w-full rounded border border-line bg-white px-3 py-2 text-sm md:w-72"
|
||||
type="search"
|
||||
placeholder="파일명, 경로, 카테고리, 사용처 검색"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p v-if="errorMessage" class="admin-media__error mt-6 rounded border border-red-200 bg-red-50 px-4 py-3 text-sm text-red-700">
|
||||
@@ -233,6 +267,29 @@ const deleteMedia = async (item) => {
|
||||
</div>
|
||||
</dl>
|
||||
|
||||
<div class="admin-media__category grid gap-2">
|
||||
<label class="admin-media__category-label text-xs font-semibold text-muted" for="media-category">
|
||||
카테고리
|
||||
</label>
|
||||
<div class="admin-media__category-row flex gap-2">
|
||||
<input
|
||||
id="media-category"
|
||||
v-model="editingCategory"
|
||||
class="admin-media__category-input min-w-0 flex-1 rounded border border-line px-3 py-2 text-sm"
|
||||
type="text"
|
||||
list="media-category-options"
|
||||
placeholder="미분류"
|
||||
@keydown.enter.prevent="saveMediaCategory"
|
||||
>
|
||||
<button class="admin-media__category-save rounded border border-line px-3 py-2 text-xs font-semibold" type="button" @click="saveMediaCategory">
|
||||
저장
|
||||
</button>
|
||||
</div>
|
||||
<datalist id="media-category-options">
|
||||
<option v-for="category in mediaCategories" :key="category" :value="category" />
|
||||
</datalist>
|
||||
</div>
|
||||
|
||||
<div class="admin-media__usage rounded bg-surface p-3 text-xs">
|
||||
<strong class="admin-media__usage-title text-ink">
|
||||
사용 현황 {{ selectedMedia.usage.length }}곳
|
||||
|
||||
Reference in New Issue
Block a user