190 lines
4.7 KiB
Vue
190 lines
4.7 KiB
Vue
<template>
|
|
<header class="top-nav">
|
|
<div class="top-nav__left">
|
|
<button
|
|
v-if="props.iconNavCollapsed !== undefined"
|
|
class="top-nav__icon-btn"
|
|
@click="emit('toggleIconNav')"
|
|
title="切换导航"
|
|
>
|
|
<MenuFoldOutlined v-if="!iconNavCollapsed" />
|
|
<MenuUnfoldOutlined v-else />
|
|
</button>
|
|
<div class="top-nav__logo" @click="router.push('/agent')">
|
|
<span class="top-nav__logo-text">Fischer</span>
|
|
<span class="top-nav__logo-badge">AgentKit</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="top-nav__center">
|
|
</div>
|
|
|
|
<div class="top-nav__right">
|
|
<div class="top-nav__status">
|
|
<a-badge
|
|
:status="wsConnected ? 'success' : 'error'"
|
|
:text="wsConnected ? '已连接' : '未连接'"
|
|
/>
|
|
</div>
|
|
<a-tooltip title="多维表格">
|
|
<button class="top-nav__icon-btn" aria-label="多维表格" @click="router.push('/bitable')">
|
|
<TableOutlined />
|
|
</button>
|
|
</a-tooltip>
|
|
<a-tooltip :title="isDark ? '切换亮色模式' : '切换暗色模式'">
|
|
<button
|
|
class="top-nav__icon-btn"
|
|
:aria-label="isDark ? '切换亮色模式' : '切换暗色模式'"
|
|
@click="themeStore.toggle()"
|
|
>
|
|
<BulbOutlined v-if="isDark" />
|
|
<BulbOutlined v-else style="opacity: 0.5" />
|
|
</button>
|
|
</a-tooltip>
|
|
<a-tooltip title="设置">
|
|
<button class="top-nav__icon-btn" @click="router.push('/agent/monitor?tab=settings')">
|
|
<SettingOutlined />
|
|
</button>
|
|
</a-tooltip>
|
|
<a-tooltip v-if="authStore.isAdmin()" title="管理控制台">
|
|
<button class="top-nav__icon-btn" @click="router.push('/admin/dashboard')">
|
|
<TeamOutlined />
|
|
</button>
|
|
</a-tooltip>
|
|
</div>
|
|
</header>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { computed } from 'vue'
|
|
import { useRouter } from 'vue-router'
|
|
import { Badge as ABadge, Tooltip as ATooltip } from 'ant-design-vue'
|
|
import {
|
|
SettingOutlined,
|
|
MenuFoldOutlined,
|
|
MenuUnfoldOutlined,
|
|
BulbOutlined,
|
|
TeamOutlined,
|
|
TableOutlined,
|
|
} from '@ant-design/icons-vue'
|
|
import { useChatStore } from '@/stores/chat'
|
|
import { useThemeStore } from '@/stores/theme'
|
|
import { useAuthStore } from '@/stores/auth'
|
|
|
|
const props = defineProps<{
|
|
iconNavCollapsed?: boolean
|
|
}>()
|
|
|
|
const emit = defineEmits<{
|
|
toggleIconNav: []
|
|
}>()
|
|
|
|
const router = useRouter()
|
|
const chatStore = useChatStore()
|
|
const themeStore = useThemeStore()
|
|
const authStore = useAuthStore()
|
|
const wsConnected = computed(() => chatStore.isWsConnected)
|
|
const iconNavCollapsed = computed(() => props.iconNavCollapsed ?? false)
|
|
const isDark = computed(() => themeStore.resolvedMode === 'dark')
|
|
</script>
|
|
|
|
<style scoped>
|
|
.top-nav {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
height: var(--topnav-height);
|
|
padding: 0 var(--space-5);
|
|
background: var(--bg-primary);
|
|
border-bottom: 1px solid var(--border-color-split);
|
|
flex-shrink: 0;
|
|
z-index: 100;
|
|
}
|
|
|
|
.top-nav__left {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: var(--space-3);
|
|
}
|
|
|
|
.top-nav__logo {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: var(--space-2);
|
|
cursor: pointer;
|
|
user-select: none;
|
|
padding: var(--space-1) var(--space-2);
|
|
border-radius: var(--radius-md);
|
|
transition: background var(--transition-fast);
|
|
}
|
|
|
|
.top-nav__logo:hover {
|
|
background: var(--bg-tertiary);
|
|
}
|
|
|
|
.top-nav__logo-text {
|
|
font-size: var(--font-lg);
|
|
font-weight: var(--font-weight-bold);
|
|
background: var(--gradient-brand);
|
|
-webkit-background-clip: text;
|
|
-webkit-text-fill-color: transparent;
|
|
background-clip: text;
|
|
}
|
|
|
|
.top-nav__logo-badge {
|
|
font-size: var(--font-xs);
|
|
font-weight: var(--font-weight-medium);
|
|
color: var(--text-inverse);
|
|
background: var(--gradient-brand);
|
|
padding: 2px var(--space-2);
|
|
border-radius: var(--radius-full);
|
|
letter-spacing: 0.3px;
|
|
}
|
|
|
|
.top-nav__center {
|
|
display: flex;
|
|
align-items: center;
|
|
}
|
|
|
|
.top-nav__task-select {
|
|
min-width: 200px;
|
|
}
|
|
|
|
.top-nav__right {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: var(--space-2);
|
|
}
|
|
|
|
.top-nav__status {
|
|
font-size: var(--font-xs);
|
|
padding: var(--space-1) var(--space-2);
|
|
border-radius: var(--radius-full);
|
|
background: var(--bg-tertiary);
|
|
}
|
|
|
|
.top-nav__status :deep(.ant-badge-status-text) {
|
|
color: var(--text-tertiary);
|
|
font-size: var(--font-xs);
|
|
}
|
|
|
|
.top-nav__icon-btn {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
width: 34px;
|
|
height: 34px;
|
|
border: none;
|
|
background: transparent;
|
|
color: var(--text-tertiary);
|
|
cursor: pointer;
|
|
border-radius: var(--radius-md);
|
|
transition: all var(--transition-fast);
|
|
}
|
|
|
|
.top-nav__icon-btn:hover {
|
|
color: var(--text-primary);
|
|
background: var(--bg-tertiary);
|
|
}
|
|
</style>
|