메뉴 관리 개편, 추천 사이트·1뎁스 네비, 우측 Recommended 연동(v1.1.13)
상단 네비는 평면 테이블·드래그로 편집하고 한 단계 하위만 허용한다. 추천 사이트 탭·location recommended·공개 API와 우측 사이드 카드·파비콘 URL 유틸을 추가한다. 문서·배포 마이그레이션 안내·관리자 레이아웃·설정 화면 등 누적 변경을 반영한다.
This commit is contained in:
@@ -1,12 +1,26 @@
|
||||
<script setup>
|
||||
const route = useRoute()
|
||||
const runtimeConfig = useRuntimeConfig()
|
||||
|
||||
/**
|
||||
* 공개 블로그 베이스 URL (후행 슬래시 제거, 새 창 링크용)
|
||||
* @returns {string} 절대 URL
|
||||
*/
|
||||
const publicBlogBaseUrl = computed(() => {
|
||||
const raw = String(runtimeConfig.public?.siteUrl || '').trim()
|
||||
return raw.replace(/\/+$/, '') || 'https://sori.studio'
|
||||
})
|
||||
|
||||
const isPostEditorRoute = computed(() => route.path === '/admin/posts/new'
|
||||
|| (route.path.startsWith('/admin/posts/') && route.path !== '/admin/posts/preview'))
|
||||
|
||||
const editorDocumentClass = 'admin-post-editor-document'
|
||||
const settingsDocumentClass = 'admin-settings-document'
|
||||
const adminUserMenuOpen = ref(false)
|
||||
|
||||
const isAdminSettingsRoute = computed(() => route.path === '/admin/settings'
|
||||
|| route.path.startsWith('/admin/settings/'))
|
||||
|
||||
const { data: adminMember } = await useFetch('/api/auth/me', {
|
||||
default: () => ({
|
||||
username: '',
|
||||
@@ -67,19 +81,23 @@ const onAdminDocumentPointerDown = (event) => {
|
||||
}
|
||||
|
||||
/**
|
||||
* 글쓰기 전체 화면 문서 스크롤 잠금 적용
|
||||
* 글쓰기·설정 전체 화면 문서 스크롤 잠금 적용
|
||||
* @returns {void}
|
||||
*/
|
||||
const syncPostEditorDocumentClass = () => {
|
||||
const syncAdminShellDocumentClass = () => {
|
||||
if (!import.meta.client) {
|
||||
return
|
||||
}
|
||||
|
||||
document.documentElement.classList.toggle(editorDocumentClass, isPostEditorRoute.value)
|
||||
document.body.classList.toggle(editorDocumentClass, isPostEditorRoute.value)
|
||||
const editorOn = isPostEditorRoute.value
|
||||
const settingsOn = isAdminSettingsRoute.value && !editorOn
|
||||
document.documentElement.classList.toggle(editorDocumentClass, editorOn)
|
||||
document.body.classList.toggle(editorDocumentClass, editorOn)
|
||||
document.documentElement.classList.toggle(settingsDocumentClass, settingsOn)
|
||||
document.body.classList.toggle(settingsDocumentClass, settingsOn)
|
||||
}
|
||||
|
||||
watchEffect(syncPostEditorDocumentClass)
|
||||
watchEffect(syncAdminShellDocumentClass)
|
||||
|
||||
onMounted(() => {
|
||||
document.addEventListener('pointerdown', onAdminDocumentPointerDown)
|
||||
@@ -92,6 +110,8 @@ onBeforeUnmount(() => {
|
||||
|
||||
document.documentElement.classList.remove(editorDocumentClass)
|
||||
document.body.classList.remove(editorDocumentClass)
|
||||
document.documentElement.classList.remove(settingsDocumentClass)
|
||||
document.body.classList.remove(settingsDocumentClass)
|
||||
document.removeEventListener('pointerdown', onAdminDocumentPointerDown)
|
||||
})
|
||||
|
||||
@@ -111,10 +131,10 @@ const logoutAdmin = async () => {
|
||||
<template>
|
||||
<div
|
||||
class="admin-layout bg-[#f7f8fa] text-ink"
|
||||
:class="isPostEditorRoute ? 'h-screen overflow-hidden bg-white' : 'min-h-screen'"
|
||||
:class="(isPostEditorRoute || isAdminSettingsRoute) ? 'h-screen overflow-hidden bg-white' : 'min-h-screen'"
|
||||
>
|
||||
<aside
|
||||
v-if="!isPostEditorRoute"
|
||||
v-if="!isPostEditorRoute && !isAdminSettingsRoute"
|
||||
class="admin-layout__sidebar fixed inset-y-0 left-0 hidden w-80 flex-col border-r border-[#e6e8eb] bg-[#f7f8fa] px-5 py-6 text-[#15171a] lg:flex"
|
||||
>
|
||||
<NuxtLink class="admin-layout__brand flex items-center gap-3 px-2 text-[0.95rem] font-semibold tracking-[-0.01em]" to="/admin">
|
||||
@@ -124,6 +144,29 @@ const logoutAdmin = async () => {
|
||||
<span>sori.studio</span>
|
||||
</NuxtLink>
|
||||
<nav class="admin-layout__nav mt-10 grid gap-1.5 text-sm font-medium text-[#5d6673]">
|
||||
<div
|
||||
class="admin-layout__nav-link admin-layout__nav-link--disabled flex cursor-not-allowed items-center gap-3 rounded-md px-3 py-2 text-[#9aa3ad] select-none"
|
||||
aria-disabled="true"
|
||||
title="준비 중"
|
||||
>
|
||||
<svg class="admin-layout__nav-icon h-4 w-4 shrink-0 opacity-60" viewBox="0 0 24 24" aria-hidden="true">
|
||||
<path d="M22.272 23.247a.981.981 0 00.978-.978V9.747a1.181 1.181 0 00-.377-.8L12 .747l-10.873 8.2a1.181 1.181 0 00-.377.8v12.522a.981.981 0 00.978.978z" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" />
|
||||
</svg>
|
||||
<span>대시보드</span>
|
||||
</div>
|
||||
<a
|
||||
class="admin-layout__nav-link admin-layout__nav-link--external flex items-center gap-3 rounded-md px-3 py-2 text-[#5d6673] transition-colors hover:bg-[#eceff2] hover:text-[#15171a]"
|
||||
:href="publicBlogBaseUrl"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<svg class="admin-layout__nav-icon h-4 w-4 shrink-0" viewBox="0 0 24 24" aria-hidden="true">
|
||||
<rect x="1.5" y="1.497" width="21" height="21" rx="1.5" ry="1.5" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" />
|
||||
<path d="M1.5 7.497h21m-13.5 15v-15" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" />
|
||||
</svg>
|
||||
<span>사이트 보기</span>
|
||||
</a>
|
||||
<div class="admin-layout__nav-divider h-6 shrink-0" aria-hidden="true" />
|
||||
<div
|
||||
class="admin-layout__nav-item group flex items-center rounded-md transition-colors"
|
||||
:class="isAdminNavActive('/admin/posts') ? 'bg-[#e9ecef] text-[#15171a]' : 'hover:bg-[#eceff2] hover:text-[#15171a]'"
|
||||
@@ -260,10 +303,12 @@ const logoutAdmin = async () => {
|
||||
</div>
|
||||
</aside>
|
||||
<main
|
||||
class="admin-layout__main bg-paper"
|
||||
class="admin-layout__main"
|
||||
:class="[
|
||||
isPostEditorRoute ? 'h-screen overflow-hidden' : 'min-h-screen px-8 py-8 xl:px-12 xl:py-10',
|
||||
{ 'lg:ml-80': !isPostEditorRoute }
|
||||
isPostEditorRoute || isAdminSettingsRoute
|
||||
? 'h-screen overflow-hidden bg-white'
|
||||
: 'min-h-screen bg-paper px-8 py-8 xl:px-12 xl:py-10',
|
||||
{ 'lg:ml-80': !isPostEditorRoute && !isAdminSettingsRoute }
|
||||
]"
|
||||
>
|
||||
<slot />
|
||||
|
||||
Reference in New Issue
Block a user