feat: offline status
This commit is contained in:
parent
6d7d6cde37
commit
044a4b56e2
4
auto-imports.d.ts
vendored
4
auto-imports.d.ts
vendored
@ -34,6 +34,7 @@ declare global {
|
||||
const defineComponent: typeof import('vue')['defineComponent']
|
||||
const defineLoader: typeof import('vue-router/auto')['defineLoader']
|
||||
const definePage: typeof import('unplugin-vue-router/runtime')['definePage']
|
||||
const doCheckOnline: typeof import('./src/composables/fetch')['doCheckOnline']
|
||||
const eagerComputed: typeof import('@vueuse/core')['eagerComputed']
|
||||
const effectScope: typeof import('vue')['effectScope']
|
||||
const extendRef: typeof import('@vueuse/core')['extendRef']
|
||||
@ -132,6 +133,7 @@ declare global {
|
||||
const useAsyncQueue: typeof import('@vueuse/core')['useAsyncQueue']
|
||||
const useAsyncState: typeof import('@vueuse/core')['useAsyncState']
|
||||
const useAttrs: typeof import('vue')['useAttrs']
|
||||
const useBackendOnline: typeof import('./src/composables/fetch')['useBackendOnline']
|
||||
const useBase64: typeof import('@vueuse/core')['useBase64']
|
||||
const useBattery: typeof import('@vueuse/core')['useBattery']
|
||||
const useBluetooth: typeof import('@vueuse/core')['useBluetooth']
|
||||
@ -334,6 +336,7 @@ declare module 'vue' {
|
||||
readonly debouncedWatch: UnwrapRef<typeof import('@vueuse/core')['debouncedWatch']>
|
||||
readonly defineAsyncComponent: UnwrapRef<typeof import('vue')['defineAsyncComponent']>
|
||||
readonly defineComponent: UnwrapRef<typeof import('vue')['defineComponent']>
|
||||
readonly doCheckOnline: UnwrapRef<typeof import('./src/composables/fetch')['doCheckOnline']>
|
||||
readonly eagerComputed: UnwrapRef<typeof import('@vueuse/core')['eagerComputed']>
|
||||
readonly effectScope: UnwrapRef<typeof import('vue')['effectScope']>
|
||||
readonly extendRef: UnwrapRef<typeof import('@vueuse/core')['extendRef']>
|
||||
@ -432,6 +435,7 @@ declare module 'vue' {
|
||||
readonly useAsyncQueue: UnwrapRef<typeof import('@vueuse/core')['useAsyncQueue']>
|
||||
readonly useAsyncState: UnwrapRef<typeof import('@vueuse/core')['useAsyncState']>
|
||||
readonly useAttrs: UnwrapRef<typeof import('vue')['useAttrs']>
|
||||
readonly useBackendOnline: UnwrapRef<typeof import('./src/composables/fetch')['useBackendOnline']>
|
||||
readonly useBase64: UnwrapRef<typeof import('@vueuse/core')['useBase64']>
|
||||
readonly useBattery: UnwrapRef<typeof import('@vueuse/core')['useBattery']>
|
||||
readonly useBluetooth: UnwrapRef<typeof import('@vueuse/core')['useBluetooth']>
|
||||
|
||||
1
components.d.ts
vendored
1
components.d.ts
vendored
@ -56,6 +56,7 @@ declare module 'vue' {
|
||||
CollapsibleTrigger: typeof import('./src/components/ui/collapsible/CollapsibleTrigger.vue')['default']
|
||||
Day_cycle_power_wave_plot: typeof import('./src/components/dense/saber/day_cycle_power_wave_plot.vue')['default']
|
||||
Day_fft_ifft_plot: typeof import('./src/components/dense/saber/day_fft_ifft_plot.vue')['default']
|
||||
DefaultLayout: typeof import('./src/components/DefaultLayout.vue')['default']
|
||||
DenseFramework: typeof import('./src/components/DenseFramework.vue')['default']
|
||||
Drawer: typeof import('./src/components/ui/drawer/Drawer.vue')['default']
|
||||
DrawerContent: typeof import('./src/components/ui/drawer/DrawerContent.vue')['default']
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
<meta name="description" content="Opinionated Vite Starter Template" />
|
||||
</head>
|
||||
<body class="font-sans dark:text-white dark:bg-hex-121212">
|
||||
<div id="app"></div>
|
||||
<div id="app" class="w-full h-full"></div>
|
||||
<noscript>
|
||||
<div>Please enable JavaScript to use this application.</div>
|
||||
</noscript>
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
"packageManager": "pnpm@9.14.4",
|
||||
"scripts": {
|
||||
"build": "vite build",
|
||||
"dev": "vite --port 3333 --open",
|
||||
"dev": "vite --port 10514 --open",
|
||||
"lint": "eslint .",
|
||||
"typecheck": "vue-tsc --noEmit",
|
||||
"preview": "vite preview",
|
||||
|
||||
301
src/App.vue
301
src/App.vue
@ -1,295 +1,22 @@
|
||||
<script setup lang="ts">
|
||||
import { Icon } from '@iconify/vue'
|
||||
import { useBackendOnline } from './composables'
|
||||
|
||||
import { ChevronRight, ChevronsUpDown } from 'lucide-vue-next'
|
||||
import {
|
||||
Breadcrumb,
|
||||
BreadcrumbItem,
|
||||
BreadcrumbLink,
|
||||
BreadcrumbList,
|
||||
BreadcrumbPage,
|
||||
BreadcrumbSeparator,
|
||||
} from '~/components/ui/breadcrumb'
|
||||
|
||||
import {
|
||||
Collapsible,
|
||||
CollapsibleContent,
|
||||
CollapsibleTrigger,
|
||||
} from '~/components/ui/collapsible'
|
||||
import { Separator } from '~/components/ui/separator'
|
||||
|
||||
import {
|
||||
Sidebar,
|
||||
SidebarContent,
|
||||
SidebarFooter,
|
||||
SidebarGroup,
|
||||
SidebarGroupLabel,
|
||||
SidebarInset,
|
||||
SidebarMenu,
|
||||
SidebarMenuButton,
|
||||
SidebarMenuItem,
|
||||
SidebarMenuSub,
|
||||
SidebarMenuSubButton,
|
||||
SidebarMenuSubItem,
|
||||
SidebarProvider,
|
||||
SidebarRail,
|
||||
} from '~/components/ui/sidebar'
|
||||
import { authCode } from './composables'
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
function logout() {
|
||||
localStorage.clear()
|
||||
sessionStorage.clear()
|
||||
authCode.value = ''
|
||||
router.push('/auth')
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
if (!authCode.value) {
|
||||
router.push('/auth')
|
||||
}
|
||||
})
|
||||
// This is sample data.
|
||||
const data = {
|
||||
user: {
|
||||
name: 'shadcn',
|
||||
email: 'm@example.com',
|
||||
avatar: '/avatars/shadcn.jpg',
|
||||
},
|
||||
navMain: [
|
||||
{
|
||||
title: '流星雷达',
|
||||
url: '#',
|
||||
icon: 'ri-radar-fill',
|
||||
isActive: true,
|
||||
items: [
|
||||
{
|
||||
title: '潮汐波提取',
|
||||
url: '/radar/TW-single',
|
||||
},
|
||||
{
|
||||
title: '潮汐波统计',
|
||||
url: '/radar/TW-stats',
|
||||
},
|
||||
{
|
||||
title: '行星波提取',
|
||||
url: '/radar/PW-single',
|
||||
},
|
||||
{
|
||||
title: '行星波统计',
|
||||
url: '/radar/PW-stats',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'SABER',
|
||||
url: '#',
|
||||
icon: 'game-icons:cracked-saber',
|
||||
isActive: true,
|
||||
items: [
|
||||
{
|
||||
title: '重力波提取',
|
||||
url: '/saber/gw/single',
|
||||
},
|
||||
{
|
||||
title: '重力波统计',
|
||||
url: '/saber/gw/stats',
|
||||
},
|
||||
],
|
||||
|
||||
},
|
||||
{
|
||||
title: '探空气球',
|
||||
url: '#',
|
||||
icon: 'bxs:balloon',
|
||||
isActive: true,
|
||||
items: [
|
||||
{
|
||||
title: '重力波单次',
|
||||
url: '/balloon/single',
|
||||
},
|
||||
{
|
||||
title: '重力波统计',
|
||||
url: '/balloon/year',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'TIDI',
|
||||
url: '#',
|
||||
icon: 'mdi:telescope',
|
||||
isActive: true,
|
||||
items: [
|
||||
{
|
||||
title: '行星波振幅',
|
||||
url: '/tidi/waves',
|
||||
},
|
||||
{
|
||||
title: '行星波月统计',
|
||||
url: '/tidi/month_stats',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'COSMIC',
|
||||
url: '#',
|
||||
icon: 'mdi:telescope',
|
||||
isActive: true,
|
||||
items: [
|
||||
{
|
||||
title: '行星波月统计',
|
||||
url: '/cosmic/stats',
|
||||
},
|
||||
{
|
||||
title: '行星波单次',
|
||||
url: '/cosmic/single',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
|
||||
关于: [
|
||||
{
|
||||
name: 'Design Engineering',
|
||||
url: '#',
|
||||
icon: 'Frame',
|
||||
},
|
||||
|
||||
],
|
||||
} as const
|
||||
const online = useBackendOnline()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<div v-if="$route.path === '/auth'">
|
||||
<RouterView />
|
||||
</div>
|
||||
<div v-else>
|
||||
<SidebarProvider>
|
||||
<Sidebar collapsible="icon">
|
||||
<SidebarHeader>
|
||||
<Alert>
|
||||
<AlertTitle>服务状态正常</AlertTitle>
|
||||
</Alert>
|
||||
</SidebarHeader>
|
||||
<SidebarContent>
|
||||
<SidebarGroup>
|
||||
<SidebarGroupLabel>模型</SidebarGroupLabel>
|
||||
<SidebarMenu>
|
||||
<Collapsible
|
||||
v-for="item in data.navMain"
|
||||
:key="item.title"
|
||||
as-child
|
||||
:default-open="item.isActive"
|
||||
class="group/collapsible"
|
||||
>
|
||||
<SidebarMenuItem>
|
||||
<CollapsibleTrigger as-child>
|
||||
<SidebarMenuButton :tooltip="item.title">
|
||||
<Icon :icon="item.icon" />
|
||||
<span>{{ item.title }}</span>
|
||||
<ChevronRight class="ml-auto transition-transform duration-200 group-data-[state=open]/collapsible:rotate-90" />
|
||||
</SidebarMenuButton>
|
||||
</CollapsibleTrigger>
|
||||
|
||||
<CollapsibleContent>
|
||||
<SidebarMenuSub>
|
||||
<SidebarMenuSubItem
|
||||
v-for="subItem in item.items"
|
||||
:key="subItem.title"
|
||||
class="hover:bg-gray-100"
|
||||
>
|
||||
<SidebarMenuSubButton as-child>
|
||||
<RouterLink
|
||||
:to="subItem.url"
|
||||
active-class="bg-accent-foreground text-accent"
|
||||
>
|
||||
<span> </span>
|
||||
<span>{{ subItem.title }}</span>
|
||||
</RouterLink>
|
||||
</SidebarMenuSubButton>
|
||||
</SidebarMenuSubItem>
|
||||
</SidebarMenuSub>
|
||||
</CollapsibleContent>
|
||||
</SidebarMenuItem>
|
||||
</Collapsible>
|
||||
</SidebarMenu>
|
||||
</SidebarGroup>
|
||||
</SidebarContent>
|
||||
<SidebarFooter>
|
||||
<SidebarMenu>
|
||||
<SidebarMenuItem flex="~ row items-center gap-2">
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger as-child>
|
||||
<SidebarMenuButton
|
||||
size="lg"
|
||||
class="data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground"
|
||||
>
|
||||
<div class="grid flex-1 text-left text-sm leading-tight">
|
||||
<span class="truncate font-semibold">操作员</span>
|
||||
<span class="truncate text-xs">已授权</span>
|
||||
</div>
|
||||
<ChevronsUpDown class="ml-auto size-4" />
|
||||
</SidebarMenuButton>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent
|
||||
class="min-w-56 w-[--radix-dropdown-menu-trigger-width] rounded-lg" side="bottom" align="end"
|
||||
:side-offset="4"
|
||||
>
|
||||
<div @click="logout">
|
||||
<DropdownMenuItem>
|
||||
<Icon icon="heroicons-solid:logout" class="h-4 w-4" />
|
||||
退出系统
|
||||
</DropdownMenuItem>
|
||||
</div>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
<Button variant="outline" size="icon" class="ml-auto h-8 w-8">
|
||||
<Icon icon="icon-park-outline:setting" class="h-4 w-4" />
|
||||
<span class="sr-only">设置</span>
|
||||
</Button>
|
||||
</SidebarMenuItem>
|
||||
</SidebarMenu>
|
||||
</SidebarFooter>
|
||||
<SidebarRail />
|
||||
</Sidebar>
|
||||
<SidebarInset>
|
||||
<header class="group-has-[[data-collapsible=icon]]/sidebar-wrapper:h-12 h-16 flex shrink-0 items-center justify-between gap-2 transition-[width,height] ease-linear">
|
||||
<div class="flex items-center gap-2 px-4">
|
||||
<Icon icon="heroicons-solid:home" class="h-4 w-4" />
|
||||
<Separator orientation="vertical" class="mr-2 h-4" />
|
||||
<Breadcrumb>
|
||||
<BreadcrumbList>
|
||||
<BreadcrumbItem>
|
||||
<BreadcrumbLink href="/">
|
||||
中高层大气波动解析识别技术系统
|
||||
</BreadcrumbLink>
|
||||
</BreadcrumbItem>
|
||||
<BreadcrumbSeparator class="hidden md:block" />
|
||||
|
||||
<BreadcrumbItem class="hidden md:block">
|
||||
<BreadcrumbLink href="#">
|
||||
{{ $route.meta.group }}
|
||||
</BreadcrumbLink>
|
||||
</BreadcrumbItem>
|
||||
<BreadcrumbSeparator class="hidden md:block" />
|
||||
<BreadcrumbItem>
|
||||
<BreadcrumbPage>{{ $route.meta.item_name }}</BreadcrumbPage>
|
||||
</BreadcrumbItem>
|
||||
</BreadcrumbList>
|
||||
</Breadcrumb>
|
||||
</div>
|
||||
<div px-7>
|
||||
<Alert variant="default">
|
||||
<Icon icon="el:ok-circle" class="h-4 w-4 text-green!" />
|
||||
<AlertTitle>服务状态正常</AlertTitle>
|
||||
</Alert>
|
||||
</div>
|
||||
</header>
|
||||
<RouterView class="h-full overflow-hidden" />
|
||||
</SidebarInset>
|
||||
</SidebarProvider>
|
||||
<div h-full w-full>
|
||||
<div v-if="!online.isOnline.value" class="absolute z-1000000 h-full w-full bg-gray/4 backdrop-blur-md">
|
||||
<div class="h-full w-full flex flex-col items-center justify-center gap-3">
|
||||
<h1 class="flex flex-row items-center gap-3 text-3xl">
|
||||
<div class="i-tabler-network" />
|
||||
后端服务不在线
|
||||
</h1>
|
||||
<div>
|
||||
请检查后端是否运行, 或者服务器是否在维护
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<DefaultLayout />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
108
src/CONSTANT.ts
108
src/CONSTANT.ts
@ -2,3 +2,111 @@ const KURONEKO_API = 'http://100.89.232.74:18200'
|
||||
// export const API_BASE_URL = 'http://localhost:5000'
|
||||
export const API_BASE_URL = import.meta.env.PROD ? 'https://gca-api.dustella.net:8443' : KURONEKO_API
|
||||
// export const API_BASE_URL = 'https://gca-api.dustella.net:8443'
|
||||
|
||||
export const headerData = {
|
||||
user: {
|
||||
name: 'shadcn',
|
||||
email: 'm@example.com',
|
||||
avatar: '/avatars/shadcn.jpg',
|
||||
},
|
||||
navMain: [
|
||||
{
|
||||
title: '流星雷达',
|
||||
url: '#',
|
||||
icon: 'ri-radar-fill',
|
||||
isActive: true,
|
||||
items: [
|
||||
{
|
||||
title: '潮汐波提取',
|
||||
url: '/radar/TW-single',
|
||||
},
|
||||
{
|
||||
title: '潮汐波统计',
|
||||
url: '/radar/TW-stats',
|
||||
},
|
||||
{
|
||||
title: '行星波提取',
|
||||
url: '/radar/PW-single',
|
||||
},
|
||||
{
|
||||
title: '行星波统计',
|
||||
url: '/radar/PW-stats',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'SABER',
|
||||
url: '#',
|
||||
icon: 'game-icons:cracked-saber',
|
||||
isActive: true,
|
||||
items: [
|
||||
{
|
||||
title: '重力波提取',
|
||||
url: '/saber/gw/single',
|
||||
},
|
||||
{
|
||||
title: '重力波统计',
|
||||
url: '/saber/gw/stats',
|
||||
},
|
||||
],
|
||||
|
||||
},
|
||||
{
|
||||
title: '探空气球',
|
||||
url: '#',
|
||||
icon: 'bxs:balloon',
|
||||
isActive: true,
|
||||
items: [
|
||||
{
|
||||
title: '重力波单次',
|
||||
url: '/balloon/single',
|
||||
},
|
||||
{
|
||||
title: '重力波统计',
|
||||
url: '/balloon/year',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'TIDI',
|
||||
url: '#',
|
||||
icon: 'mdi:telescope',
|
||||
isActive: true,
|
||||
items: [
|
||||
{
|
||||
title: '行星波振幅',
|
||||
url: '/tidi/waves',
|
||||
},
|
||||
{
|
||||
title: '行星波月统计',
|
||||
url: '/tidi/month_stats',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'COSMIC',
|
||||
url: '#',
|
||||
icon: 'mdi:telescope',
|
||||
isActive: true,
|
||||
items: [
|
||||
{
|
||||
title: '行星波月统计',
|
||||
url: '/cosmic/stats',
|
||||
},
|
||||
{
|
||||
title: '行星波单次',
|
||||
url: '/cosmic/single',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
|
||||
关于: [
|
||||
{
|
||||
name: 'Design Engineering',
|
||||
url: '#',
|
||||
icon: 'Frame',
|
||||
},
|
||||
|
||||
],
|
||||
} as const
|
||||
|
||||
190
src/components/DefaultLayout.vue
Normal file
190
src/components/DefaultLayout.vue
Normal file
@ -0,0 +1,190 @@
|
||||
<script setup lang="ts">
|
||||
import { Icon } from '@iconify/vue'
|
||||
|
||||
import { ChevronRight, ChevronsUpDown } from 'lucide-vue-next'
|
||||
import {
|
||||
Breadcrumb,
|
||||
BreadcrumbItem,
|
||||
BreadcrumbLink,
|
||||
BreadcrumbList,
|
||||
BreadcrumbPage,
|
||||
BreadcrumbSeparator,
|
||||
} from '~/components/ui/breadcrumb'
|
||||
|
||||
import {
|
||||
Collapsible,
|
||||
CollapsibleContent,
|
||||
CollapsibleTrigger,
|
||||
} from '~/components/ui/collapsible'
|
||||
import { Separator } from '~/components/ui/separator'
|
||||
import {
|
||||
Sidebar,
|
||||
SidebarContent,
|
||||
SidebarFooter,
|
||||
SidebarGroup,
|
||||
SidebarGroupLabel,
|
||||
SidebarInset,
|
||||
SidebarMenu,
|
||||
SidebarMenuButton,
|
||||
SidebarMenuItem,
|
||||
SidebarMenuSub,
|
||||
SidebarMenuSubButton,
|
||||
SidebarMenuSubItem,
|
||||
SidebarProvider,
|
||||
SidebarRail,
|
||||
} from '~/components/ui/sidebar'
|
||||
|
||||
import { authCode, useBackendOnline } from '../composables'
|
||||
import { headerData as data } from '../CONSTANT'
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
function logout() {
|
||||
localStorage.clear()
|
||||
sessionStorage.clear()
|
||||
authCode.value = ''
|
||||
router.push('/auth')
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
if (!authCode.value) {
|
||||
router.push('/auth')
|
||||
}
|
||||
})
|
||||
|
||||
const online = useBackendOnline()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<div v-if="$route.path === '/auth'">
|
||||
<RouterView />
|
||||
</div>
|
||||
<div v-else>
|
||||
<SidebarProvider>
|
||||
<Sidebar collapsible="icon">
|
||||
<SidebarHeader>
|
||||
<Alert>
|
||||
<AlertTitle>服务状态正常 {{ online.isOnline }}</AlertTitle>
|
||||
</Alert>
|
||||
</SidebarHeader>
|
||||
<SidebarContent>
|
||||
<SidebarGroup>
|
||||
<SidebarGroupLabel>模型</SidebarGroupLabel>
|
||||
<SidebarMenu>
|
||||
<Collapsible
|
||||
v-for="item in data.navMain"
|
||||
:key="item.title"
|
||||
as-child
|
||||
:default-open="item.isActive"
|
||||
class="group/collapsible"
|
||||
>
|
||||
<SidebarMenuItem>
|
||||
<CollapsibleTrigger as-child>
|
||||
<SidebarMenuButton :tooltip="item.title">
|
||||
<Icon :icon="item.icon" />
|
||||
<span>{{ item.title }}</span>
|
||||
<ChevronRight class="ml-auto transition-transform duration-200 group-data-[state=open]/collapsible:rotate-90" />
|
||||
</SidebarMenuButton>
|
||||
</CollapsibleTrigger>
|
||||
|
||||
<CollapsibleContent>
|
||||
<SidebarMenuSub>
|
||||
<SidebarMenuSubItem
|
||||
v-for="subItem in item.items"
|
||||
:key="subItem.title"
|
||||
class="hover:bg-gray-100"
|
||||
>
|
||||
<SidebarMenuSubButton as-child>
|
||||
<RouterLink
|
||||
:to="subItem.url"
|
||||
active-class="bg-accent-foreground text-accent"
|
||||
>
|
||||
<span> </span>
|
||||
<span>{{ subItem.title }}</span>
|
||||
</RouterLink>
|
||||
</SidebarMenuSubButton>
|
||||
</SidebarMenuSubItem>
|
||||
</SidebarMenuSub>
|
||||
</CollapsibleContent>
|
||||
</SidebarMenuItem>
|
||||
</Collapsible>
|
||||
</SidebarMenu>
|
||||
</SidebarGroup>
|
||||
</SidebarContent>
|
||||
<SidebarFooter>
|
||||
<SidebarMenu>
|
||||
<SidebarMenuItem flex="~ row items-center gap-2">
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger as-child>
|
||||
<SidebarMenuButton
|
||||
size="lg"
|
||||
class="data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground"
|
||||
>
|
||||
<div class="grid flex-1 text-left text-sm leading-tight">
|
||||
<span class="truncate font-semibold">操作员</span>
|
||||
<span class="truncate text-xs">已授权</span>
|
||||
</div>
|
||||
<ChevronsUpDown class="ml-auto size-4" />
|
||||
</SidebarMenuButton>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent
|
||||
class="min-w-56 w-[--radix-dropdown-menu-trigger-width] rounded-lg" side="bottom" align="end"
|
||||
:side-offset="4"
|
||||
>
|
||||
<div @click="logout">
|
||||
<DropdownMenuItem>
|
||||
<Icon icon="heroicons-solid:logout" class="h-4 w-4" />
|
||||
退出系统
|
||||
</DropdownMenuItem>
|
||||
</div>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
<Button variant="outline" size="icon" class="ml-auto h-8 w-8">
|
||||
<Icon icon="icon-park-outline:setting" class="h-4 w-4" />
|
||||
<span class="sr-only">设置</span>
|
||||
</Button>
|
||||
</SidebarMenuItem>
|
||||
</SidebarMenu>
|
||||
</SidebarFooter>
|
||||
<SidebarRail />
|
||||
</Sidebar>
|
||||
<SidebarInset>
|
||||
<header class="group-has-[[data-collapsible=icon]]/sidebar-wrapper:h-12 h-16 flex shrink-0 items-center justify-between gap-2 transition-[width,height] ease-linear">
|
||||
<div class="flex items-center gap-2 px-4">
|
||||
<Icon icon="heroicons-solid:home" class="h-4 w-4" />
|
||||
<Separator orientation="vertical" class="mr-2 h-4" />
|
||||
<Breadcrumb>
|
||||
<BreadcrumbList>
|
||||
<BreadcrumbItem>
|
||||
<BreadcrumbLink href="/">
|
||||
中高层大气波动解析识别技术系统
|
||||
</BreadcrumbLink>
|
||||
</BreadcrumbItem>
|
||||
<BreadcrumbSeparator class="hidden md:block" />
|
||||
|
||||
<BreadcrumbItem class="hidden md:block">
|
||||
<BreadcrumbLink href="#">
|
||||
{{ $route.meta.group }}
|
||||
</BreadcrumbLink>
|
||||
</BreadcrumbItem>
|
||||
<BreadcrumbSeparator class="hidden md:block" />
|
||||
<BreadcrumbItem>
|
||||
<BreadcrumbPage>{{ $route.meta.item_name }}</BreadcrumbPage>
|
||||
</BreadcrumbItem>
|
||||
</BreadcrumbList>
|
||||
</Breadcrumb>
|
||||
</div>
|
||||
<div px-7>
|
||||
<Alert variant="default">
|
||||
<Icon icon="el:ok-circle" class="h-4 w-4 text-green!" />
|
||||
<AlertTitle>服务状态正常</AlertTitle>
|
||||
</Alert>
|
||||
</div>
|
||||
</header>
|
||||
<RouterView class="h-full overflow-hidden" />
|
||||
</SidebarInset>
|
||||
</SidebarProvider>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@ -11,10 +11,9 @@ export const baseFetch = createFetch({
|
||||
baseUrl: API_BASE_URL,
|
||||
options: {
|
||||
async beforeFetch({ options }) {
|
||||
const code = '0101'
|
||||
options.headers = {
|
||||
...options.headers,
|
||||
Authorization: `${code}`,
|
||||
Authorization: `${authCode.value}`,
|
||||
}
|
||||
return { options }
|
||||
},
|
||||
@ -25,3 +24,51 @@ export const baseFetch = createFetch({
|
||||
},
|
||||
|
||||
})
|
||||
|
||||
export async function doCheckOnline() {
|
||||
let resp = null
|
||||
try {
|
||||
resp = await baseFetch('/ping', {
|
||||
timeout: 2000,
|
||||
})
|
||||
const { error } = resp
|
||||
if (error.value)
|
||||
throw new Error(error.value)
|
||||
const status = resp.response.value?.status
|
||||
if (!status) {
|
||||
return false
|
||||
}
|
||||
if (status === 200) {
|
||||
return true
|
||||
}
|
||||
else if (status >= 400 && status < 500) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
catch (err) {
|
||||
if (resp?.response.value?.status === 401) {
|
||||
return true
|
||||
}
|
||||
console.error(err)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
export const useBackendOnline = createSharedComposable(() => {
|
||||
const isOnline = ref(true)
|
||||
|
||||
const useCheckInterval = useIntervalFn(() => {
|
||||
doCheckOnline().then((online) => {
|
||||
isOnline.value = online
|
||||
})
|
||||
}, 5000, {
|
||||
immediate: true,
|
||||
immediateCallback: true,
|
||||
})
|
||||
useCheckInterval.resume()
|
||||
|
||||
return {
|
||||
isOnline,
|
||||
}
|
||||
})
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user