feat: 灵犀 Studio Web UI 定制版
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,190 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
import { onMounted, onUnmounted, computed, ref, watch } from 'vue'
|
||||
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
|
||||
import { darkTheme, NConfigProvider, NMessageProvider, NDialogProvider, NNotificationProvider } from 'naive-ui'
|
||||
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
import { getThemeOverrides } from '@/styles/theme'
|
||||
|
||||
import { useTheme } from '@/composables/useTheme'
|
||||
|
||||
import AppSidebar from '@/components/layout/AppSidebar.vue'
|
||||
|
||||
import AppTopBar from '@/components/layout/AppTopBar.vue'
|
||||
|
||||
import AppLogo from '@/components/common/AppLogo.vue'
|
||||
|
||||
import { useKeyboard } from '@/composables/useKeyboard'
|
||||
|
||||
import { useAppStore } from '@/stores/hermes/app'
|
||||
|
||||
import SessionSearchModal from '@/components/hermes/chat/SessionSearchModal.vue'
|
||||
|
||||
import AuthEventListener from '@/components/auth/AuthEventListener.vue'
|
||||
|
||||
import DefaultCredentialPrompt from '@/components/auth/DefaultCredentialPrompt.vue'
|
||||
|
||||
|
||||
|
||||
const { isDark, isComic } = useTheme()
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const appStore = useAppStore()
|
||||
|
||||
const route = useRoute()
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
const ready = ref(false)
|
||||
|
||||
|
||||
|
||||
const themeOverrides = computed(() => getThemeOverrides(isDark.value, isComic.value))
|
||||
|
||||
const naiveTheme = computed(() => isDark.value ? darkTheme : null)
|
||||
|
||||
|
||||
|
||||
const isLoginPage = computed(() => route.name === 'login')
|
||||
|
||||
|
||||
|
||||
const nodeVersionLow = computed(() => {
|
||||
|
||||
const v = appStore.nodeVersion
|
||||
|
||||
const major = parseInt(v.split('.')[0], 10)
|
||||
|
||||
return !isNaN(major) && major < 23
|
||||
|
||||
})
|
||||
|
||||
|
||||
|
||||
watch(() => route.path, () => {
|
||||
|
||||
appStore.closeSidebar()
|
||||
|
||||
})
|
||||
|
||||
|
||||
|
||||
router.isReady().then(() => {
|
||||
|
||||
ready.value = true
|
||||
|
||||
})
|
||||
|
||||
|
||||
|
||||
onMounted(() => {
|
||||
|
||||
if (!isLoginPage.value) {
|
||||
|
||||
appStore.loadModels()
|
||||
|
||||
appStore.startHealthPolling()
|
||||
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
|
||||
|
||||
onUnmounted(() => {
|
||||
|
||||
appStore.stopHealthPolling()
|
||||
|
||||
})
|
||||
|
||||
|
||||
|
||||
useKeyboard()
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
<template>
|
||||
|
||||
<NConfigProvider :theme="naiveTheme" :theme-overrides="themeOverrides">
|
||||
|
||||
<NMessageProvider>
|
||||
|
||||
<AuthEventListener />
|
||||
|
||||
<NDialogProvider>
|
||||
|
||||
<NNotificationProvider>
|
||||
|
||||
<div v-if="nodeVersionLow && ready" class="node-warning-bar">
|
||||
|
||||
{{ t('sidebar.nodeVersionWarning', { version: appStore.nodeVersion }) }}
|
||||
|
||||
</div>
|
||||
|
||||
<div v-if="ready" class="app-shell" :class="{ 'no-chrome': isLoginPage, 'has-warning': nodeVersionLow }">
|
||||
|
||||
<AppTopBar v-if="!isLoginPage" />
|
||||
|
||||
<button v-if="!isLoginPage" class="hamburger-btn" @click="appStore.toggleSidebar">
|
||||
|
||||
<AppLogo :size="22" />
|
||||
|
||||
</button>
|
||||
|
||||
<div v-if="!isLoginPage && appStore.sidebarOpen" class="mobile-backdrop" @click="appStore.closeSidebar" />
|
||||
|
||||
<div v-if="!isLoginPage" class="app-body">
|
||||
|
||||
<AppSidebar />
|
||||
|
||||
<main class="app-main">
|
||||
|
||||
<router-view />
|
||||
|
||||
</main>
|
||||
|
||||
</div>
|
||||
|
||||
<main v-else class="app-main app-main--full">
|
||||
|
||||
<router-view />
|
||||
|
||||
</main>
|
||||
|
||||
</div>
|
||||
|
||||
<SessionSearchModal />
|
||||
|
||||
<DefaultCredentialPrompt />
|
||||
|
||||
</NNotificationProvider>
|
||||
|
||||
</NDialogProvider>
|
||||
|
||||
</NMessageProvider>
|
||||
|
||||
</NConfigProvider>
|
||||
|
||||
</template>
|
||||
|
||||
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
@use '@/styles/variables' as *;
|
||||
|
||||
|
||||
|
||||
.app-shell {
|
||||
|
||||
display: flex;
|
||||
|
||||
flex-direction: column;
|
||||
|
||||
Reference in New Issue
Block a user