Files
ai-write/src/components/GlobalSidebar.vue

228 lines
5.2 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<aside class="sidebar">
<!-- Logo/Home -->
<button
class="sidebar-logo"
:class="{ active: currentPage === 'home' }"
title="主页"
@click="switchPage('home')"
>
<img src="/logo.png" alt="Home" class="sidebar-logo-img">
</button>
<!-- 导航项 -->
<nav class="sidebar-nav">
<button
v-for="item in navItems"
:key="item.id"
@click="switchPage(item.id)"
:class="['nav-item', { active: currentPage === item.id }]"
:title="item.label"
:aria-label="item.label"
>
<IconLibrary :name="item.icon" :size="20" class="nav-icon" />
<!-- Tooltip -->
<div class="nav-tooltip">
{{ item.label }}
<div class="nav-tooltip-arrow"></div>
</div>
<!-- Active Indicator -->
<div v-if="currentPage === item.id" class="nav-indicator"></div>
</button>
</nav>
<!-- 底部设置 -->
<div class="sidebar-footer">
<button
@click="switchPage('settings')"
:class="['nav-item', { active: currentPage === 'settings' }]"
title="设置"
aria-label="设置"
>
<IconLibrary name="settings" :size="20" class="nav-icon" />
<div class="nav-tooltip">
设置
<div class="nav-tooltip-arrow"></div>
</div>
</button>
</div>
</aside>
</template>
<script setup>
import { computed } from 'vue'
import { useAppStore } from '../stores/app'
import IconLibrary from './icons/IconLibrary.vue'
const appStore = useAppStore()
const currentPage = computed(() => appStore.currentPage)
const navItems = [
{ id: 'writer', label: 'AI 写作', icon: 'edit' },
{ id: 'mimicWriter', label: '以稿写稿', icon: 'copy' },
{ id: 'analysis', label: '范式库', icon: 'analysis' },
{ id: 'paradigmWriter', label: '范式写作', icon: 'article' },
{ id: 'outlineWriter', label: '提纲写作', icon: 'folder' },
{ id: 'articleEditor', label: '文章修改', icon: 'edit' },
{ id: 'articleFusion', label: '文章融合', icon: 'sparkles' },
{ id: 'documents', label: '文稿库', icon: 'folder' },
{ id: 'materials', label: '素材库', icon: 'chart' },
{ id: 'rewrite', label: '范式润色', icon: 'sparkles' },
{ id: 'compare', label: '对照检查', icon: 'compare' },
{ id: 'diffAnnotation', label: '差异标注', icon: 'chart' }
]
const switchPage = (page) => {
appStore.setCurrentPage(page)
}
</script>
<style scoped>
/* 侧边栏容器 */
.sidebar {
width: 64px;
height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
padding: var(--space-6) 0;
background: var(--bg-primary);
border-right: 1px solid var(--border-default);
flex-shrink: 0;
z-index: 50;
}
/* Logo */
.sidebar-logo {
display: flex;
align-items: center;
justify-content: center;
width: 40px;
height: 40px;
margin-bottom: var(--space-8);
color: var(--accent-primary);
transition: all var(--transition-normal);
background: transparent;
border: none;
border-radius: var(--radius-lg);
cursor: pointer;
}
.sidebar-logo:hover {
color: var(--accent-primary-hover);
transform: scale(1.05);
}
.sidebar-logo.active {
background: var(--info-bg);
box-shadow: 0 0 15px rgba(96, 165, 250, 0.2);
}
.sidebar-logo-img {
width: 100%;
height: 100%;
object-fit: cover;
border-radius: inherit;
}
/* 导航区域 */
.sidebar-nav {
flex: 1;
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
gap: var(--space-3);
}
/* 导航项 */
.nav-item {
position: relative;
width: 48px;
height: 48px;
border-radius: var(--radius-xl);
display: flex;
align-items: center;
justify-content: center;
color: var(--text-muted);
transition: all var(--transition-normal);
cursor: pointer;
background: transparent;
border: none;
}
.nav-item:hover {
background: var(--bg-elevated);
color: var(--text-secondary);
}
.nav-item.active {
background: var(--accent-primary);
color: var(--text-inverse);
box-shadow: 0 0 15px rgba(96, 165, 250, 0.4);
}
.nav-icon {
flex-shrink: 0;
display: flex;
align-items: center;
justify-content: center;
}
/* Tooltip */
.nav-tooltip {
position: absolute;
left: 100%;
margin-left: var(--space-3);
padding: var(--space-2) var(--space-3);
background: var(--bg-secondary);
color: var(--text-primary);
font-size: var(--text-xs);
font-weight: var(--font-medium);
border-radius: var(--radius-md);
opacity: 0;
visibility: hidden;
transition: all var(--transition-fast);
white-space: nowrap;
z-index: 50;
box-shadow: var(--shadow-md);
border: 1px solid var(--border-default);
pointer-events: none;
}
.nav-item:hover .nav-tooltip {
opacity: 1;
visibility: visible;
}
.nav-tooltip-arrow {
position: absolute;
left: -4px;
top: 50%;
transform: translateY(-50%);
width: 8px;
height: 8px;
background: var(--bg-secondary);
border-left: 1px solid var(--border-default);
border-bottom: 1px solid var(--border-default);
rotate: 45deg;
}
/* 激活指示器 */
.nav-indicator {
position: absolute;
left: 0;
width: 4px;
height: 24px;
background: var(--text-inverse);
border-radius: 0 var(--radius-full) var(--radius-full) 0;
}
/* 底部区域 */
.sidebar-footer {
margin-top: auto;
}
</style>