릴리스: v1.3.36 관리자 아이템 라이브러리 보강

This commit is contained in:
2026-04-01 16:30:58 +09:00
parent 7e80320e9f
commit 5f6f01942e
7 changed files with 104 additions and 43 deletions

View File

@@ -684,6 +684,7 @@ function submitGlobalSearch() {
align-items: center;
padding: 0 12px;
border-bottom: 1px solid var(--theme-border);
background: var(--theme-rail-bg);
box-sizing: border-box;
}

View File

@@ -400,6 +400,12 @@ function setTab(tab) {
if (tab === 'tierlists') {
tierlistsMode.value = 'requests'
}
if (tab === 'items') {
customItemQuery.value = ''
customItemOrphanOnly.value = false
customItemPage.value = 1
refreshCustomItems()
}
}
function setTierlistsMode(mode) {
@@ -1110,6 +1116,15 @@ function closeCustomItemDeleteModal() {
customItemDeleteModalOpen.value = false
}
function jumpToGameAdmin(gameId) {
if (!gameId) return
closeCustomItemModal()
setTab('game-admin')
nextTick(() => {
selectAdminGame(gameId)
})
}
async function removeCustomItem(item = modalTargetCustomItem.value) {
resetMessages()
if (!item) return
@@ -2016,7 +2031,7 @@ async function saveFeaturedOrder() {
<div class="customItemModal__linked">
<span class="customItemModal__label">템플릿에 사용 중인 게임</span>
<div v-if="visibleLinkedGames.length" class="customItemModal__chips">
<span v-for="game in visibleLinkedGames" :key="game.id" class="pill">{{ game.name }}</span>
<button v-for="game in visibleLinkedGames" :key="game.id" type="button" class="pill pill--link" @click="jumpToGameAdmin(game.id)">{{ game.name }}</button>
</div>
<div v-else class="hint hint--tight">아직 템플릿에 연결된 게임이 없어요.</div>
</div>
@@ -2035,7 +2050,7 @@ async function saveFeaturedOrder() {
<div v-if="customItemDeleteModalOpen" class="modalOverlay" @click.self="closeCustomItemDeleteModal">
<div class="modalCard" role="dialog" aria-modal="true">
<div class="modalCard__title">아이템 삭제</div>
<div class="modalCard__desc">{{ !modalTargetCustomItem ? '' : modalTargetCustomItem.sourceType === 'template' ? '"' + modalTargetCustomItem.label + '" 항목을 현재 템플릿에서 제거할까요? 이미 저장된 같은 게임의 티어표에서도 함께 빠질 수 있어요.' : '"' + modalTargetCustomItem.label + '" 이미지를 삭제할까요? 사용자 업로드이면서 어디에도 연결되지 않은 이미지에만 삭제를 허용합니다.' }}</div>
<div class="modalCard__desc">{{ !modalTargetCustomItem ? '' : modalTargetCustomItem.sourceType === 'template' ? '"' + modalTargetCustomItem.label + '" 항목을 정리할까요? 게임에 연결된 항목이면 해당 템플릿과 저장된 같은 게임의 티어표에서도 함께 빠질 수 있고, 보관 자산이면 라이브러리에서만 제거됩니다.' : '"' + modalTargetCustomItem.label + '" 이미지를 삭제할까요? 사용자 업로드이면서 어디에도 연결되지 않은 이미지에만 삭제를 허용합니다.' }}</div>
<div class="modalCard__actions">
<button class="btn btn--ghost" @click="closeCustomItemDeleteModal">취소</button>
<button class="btn btn--danger" @click="removeCustomItem()">삭제</button>
@@ -3171,8 +3186,8 @@ async function saveFeaturedOrder() {
}
.customItemModal {
display: grid;
grid-template-columns: minmax(280px, 320px) minmax(0, 1fr);
gap: 24px;
grid-template-columns: minmax(320px, 360px) minmax(0, 1fr);
gap: 28px;
align-items: start;
}
.customItemModal__pickerPanel {
@@ -3205,7 +3220,7 @@ async function saveFeaturedOrder() {
.customItemModal__gameList {
display: grid;
gap: 8px;
max-height: 360px;
max-height: 440px;
overflow: auto;
}
.customItemModal__gameItem {
@@ -3308,7 +3323,7 @@ async function saveFeaturedOrder() {
text-align: center;
}
.modalCard--customItem {
width: min(1160px, calc(100vw - 48px));
width: min(1280px, calc(100vw - 40px));
}
.pager {
margin-top: 16px;

View File

@@ -66,11 +66,11 @@ function openList(t) {
</script>
<template>
<section class="dashboardHero">
<div class="dashboardHero__left">
<div class="dashboardHero__eyebrow">Library</div>
<h2 class="dashboardHero__title"> 티어표</h2>
<p class="dashboardHero__desc">직접 저장한 티어표를 같은 카드 레이아웃으로 다시 열고 정리할 있어요.</p>
<section class="pageHead">
<div class="pageHead__main">
<div class="pageHead__eyebrow">Library</div>
<h2 class="pageHead__title"> 티어표</h2>
<div class="pageHead__desc">직접 저장한 티어표를 같은 카드 레이아웃으로 다시 열고 정리할 있어요.</div>
</div>
</section>
@@ -110,35 +110,6 @@ function openList(t) {
</template>
<style scoped>
.dashboardHero {
display: flex;
gap: 18px;
align-items: flex-start;
justify-content: space-between;
flex-wrap: wrap;
padding: 6px 2px 18px;
}
.dashboardHero__left {
display: grid;
gap: 8px;
}
.dashboardHero__eyebrow {
font-size: 12px;
color: var(--theme-text-soft);
text-transform: uppercase;
letter-spacing: 0.08em;
}
.dashboardHero__title {
margin: 4px 0 6px;
font-size: 32px;
letter-spacing: -0.04em;
color: var(--theme-text-strong);
}
.dashboardHero__desc {
margin: 0;
color: var(--theme-text-muted);
max-width: 720px;
}
.panel {
background: transparent;
border-radius: 0;