App.vue 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. <script setup lang="ts">
  2. import { computed, onMounted, watch } from 'vue'
  3. import { useRoute, useRouter } from 'vue-router'
  4. import LoadingScreen from '@/components/app/LoadingScreen.vue'
  5. import LoginView from '@/views/LoginView.vue'
  6. import PasswordChangeView from '@/views/PasswordChangeView.vue'
  7. import { useAuthStore } from '@/stores/auth'
  8. import { useChatStore } from '@/stores/chat'
  9. import { useKanbanStore } from '@/stores/kanban'
  10. import { useThemeStore } from '@/stores/theme'
  11. import AgentIdentityFixture from '@/components/app/AgentIdentityFixture.vue'
  12. const auth = useAuthStore()
  13. const chat = useChatStore()
  14. const kanban = useKanbanStore()
  15. const theme = useThemeStore()
  16. const route = useRoute()
  17. const router = useRouter()
  18. const allowedRoute = computed(() => !auth.isBotOnly || /^\/conversations(?:\/|$)/.test(route.path))
  19. watch([() => auth.isBotOnly, () => route.path], () => {
  20. if (!allowedRoute.value) void router.replace('/conversations')
  21. }, { immediate: true, flush: 'sync' })
  22. const agentIdentityFixture = import.meta.env.DEV
  23. && new URLSearchParams(window.location.search).get('fixture') === 'agent-identity'
  24. const pageTitle = computed(() => {
  25. const name = route.name === 'computer' ? '电脑接管' : route.name === 'bot-automations' ? '自动化' : route.path.startsWith('/history')
  26. ? '历史记录'
  27. : route.path.startsWith('/conversations')
  28. ? '聊天'
  29. : route.path.startsWith('/kanban')
  30. ? kanban.selectedBoard?.name || kanban.selectedBoardSlug || '看板'
  31. : route.path.startsWith('/files')
  32. ? '文件库'
  33. : chat.activeSession?.title || '对话'
  34. return `${name} · 夭夭 AI`
  35. })
  36. watch(() => theme.resolvedTheme, value => {
  37. document.documentElement.classList.toggle('dark', value === 'dark')
  38. document.documentElement.dataset.theme = value
  39. document.querySelector('meta[name="theme-color"]')?.setAttribute('content', value === 'dark' ? '#181817' : '#f8f8f6')
  40. }, { immediate: true })
  41. watch(pageTitle, value => { document.title = value }, { immediate: true })
  42. onMounted(() => {
  43. if (!agentIdentityFixture) void auth.bootstrap()
  44. })
  45. </script>
  46. <template>
  47. <AgentIdentityFixture v-if="agentIdentityFixture" />
  48. <LoadingScreen v-else-if="auth.status === 'checking'" />
  49. <LoginView v-else-if="!auth.isAuthenticated" />
  50. <PasswordChangeView v-else-if="auth.user?.mustChangePassword" />
  51. <RouterView v-else-if="allowedRoute" />
  52. <LoadingScreen v-else />
  53. </template>