Files
sub2api/frontend/src/App.vue
IanShaw027 506cb21cb1 refactor(frontend): UI/UX改进和组件优化
- DataTable组件操作列自适应
- 优化各种Modal弹窗
- 统一API调用方式(AbortSignal)
- 添加全局订阅状态管理
- 优化各管理视图的交互和布局
- 修复国际化翻译问题
2025-12-28 14:53:36 +08:00

90 lines
2.3 KiB
Vue

<script setup lang="ts">
import { RouterView, useRouter, useRoute } from 'vue-router'
import { onMounted, watch } from 'vue'
import Toast from '@/components/common/Toast.vue'
import { useAppStore, useAuthStore, useSubscriptionStore } from '@/stores'
import { getSetupStatus } from '@/api/setup'
const router = useRouter()
const route = useRoute()
const appStore = useAppStore()
const authStore = useAuthStore()
const subscriptionStore = useSubscriptionStore()
/**
* Update favicon dynamically
* @param logoUrl - URL of the logo to use as favicon
*/
function updateFavicon(logoUrl: string) {
// Find existing favicon link or create new one
let link = document.querySelector<HTMLLinkElement>('link[rel="icon"]')
if (!link) {
link = document.createElement('link')
link.rel = 'icon'
document.head.appendChild(link)
}
link.type = logoUrl.endsWith('.svg') ? 'image/svg+xml' : 'image/x-icon'
link.href = logoUrl
}
// Watch for site settings changes and update favicon/title
watch(
() => appStore.siteLogo,
(newLogo) => {
if (newLogo) {
updateFavicon(newLogo)
}
},
{ immediate: true }
)
watch(
() => appStore.siteName,
(newName) => {
if (newName) {
document.title = `${newName} - AI API Gateway`
}
},
{ immediate: true }
)
// Watch for authentication state and manage subscription data
watch(
() => authStore.isAuthenticated,
(isAuthenticated) => {
if (isAuthenticated) {
// User logged in: preload subscriptions and start polling
subscriptionStore.fetchActiveSubscriptions().catch((error) => {
console.error('Failed to preload subscriptions:', error)
})
subscriptionStore.startPolling()
} else {
// User logged out: clear data and stop polling
subscriptionStore.clear()
}
},
{ immediate: true }
)
onMounted(async () => {
// Check if setup is needed
try {
const status = await getSetupStatus()
if (status.needs_setup && route.path !== '/setup') {
router.replace('/setup')
return
}
} catch {
// If setup endpoint fails, assume normal mode and continue
}
// Load public settings into appStore (will be cached for other components)
await appStore.fetchPublicSettings()
})
</script>
<template>
<RouterView />
<Toast />
</template>