dramaling-app/apps/web/src/App.vue

123 lines
2.4 KiB
Vue

<template>
<div id="app">
<router-view />
<!-- 全局通知系統 -->
<ToastContainer />
<!-- 全局彈窗系統 -->
<ModalContainer />
<!-- 全局載入指示器 -->
<q-ajax-bar
position="top"
color="primary-teal"
size="4px"
/>
</div>
</template>
<script setup lang="ts">
import { onMounted, onUnmounted } from 'vue'
import { useAuthStore } from '@/stores/auth'
import { useUIStore } from '@/stores/ui'
import ToastContainer from '@/components/ui/ToastContainer.vue'
import ModalContainer from '@/components/ui/ModalContainer.vue'
const authStore = useAuthStore()
const uiStore = useUIStore()
onMounted(async () => {
// 初始化UI系統
uiStore.initializeUI()
// 初始化認證狀態
await authStore.initialize()
// 設定全局鍵盤事件監聽
document.addEventListener('keydown', handleGlobalKeydown)
})
onUnmounted(() => {
// 清理資源
uiStore.cleanup()
document.removeEventListener('keydown', handleGlobalKeydown)
})
const handleGlobalKeydown = (event: KeyboardEvent) => {
// ESC 鍵關閉彈窗和選單
if (event.key === 'Escape') {
if (uiStore.currentModal) {
uiStore.hideModal()
}
if (uiStore.mobileMenuOpen) {
uiStore.closeMobileMenu()
}
}
}
</script>
<style>
/* 全局樣式重設和基礎設定 */
#app {
font-family: 'Inter', 'Noto Sans TC', -apple-system, BlinkMacSystemFont, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
color: #2C3E50;
background: #F7F9FC;
min-height: 100vh;
width: 100%;
height: 100%;
}
/* 全局滾動條樣式 */
::-webkit-scrollbar {
width: 8px;
height: 8px;
}
::-webkit-scrollbar-track {
background: rgba(0,0,0, 0.1);
border-radius: 4px;
}
::-webkit-scrollbar-thumb {
background: rgba(0,0,0, 0.3);
border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
background: rgba(0,0,0, 0.5);
}
/* 無障礙聚焦樣式 */
*:focus-visible {
outline: 2px solid #00E5CC;
outline-offset: 2px;
border-radius: 2px;
}
/* 全局動畫 */
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.3s ease;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}
.slide-enter-active,
.slide-leave-active {
transition: transform 0.3s ease;
}
.slide-enter-from {
transform: translateX(-100%);
}
.slide-leave-to {
transform: translateX(100%);
}
</style>