feat(frontend): 统一界面图标体系
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
<script setup lang="ts">
|
||||
import type { Component } from 'vue'
|
||||
|
||||
withDefaults(defineProps<{ icon: Component; size?: number }>(), { size: 18 })
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<component :is="icon" class="app-icon" :style="{ width: `${size}px`, height: `${size}px` }" aria-hidden="true" />
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.app-icon { display: inline-block; flex: 0 0 auto; color: currentColor; }
|
||||
</style>
|
||||
@@ -1,4 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { Connection, Lightning } from '@element-plus/icons-vue'
|
||||
import AppIcon from './AppIcon.vue'
|
||||
import { computed, onMounted } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { usePluginStore } from '@/stores/plugin'
|
||||
@@ -17,13 +19,13 @@ onMounted(() => { if (isPlugin.value) void pluginStore.loadPlugins(); else void
|
||||
<div v-if="isPlugin" class="sidebar-list">
|
||||
<button v-for="plugin in pluginStore.plugins" :key="plugin.plugin_id" class="sidebar-list-item extension-item"
|
||||
:class="{ active: pluginStore.selectedPluginId === plugin.plugin_id }" @click="pluginStore.selectPlugin(plugin.plugin_id)">
|
||||
<span>{{ plugin.icon || '🧩' }}</span><span><strong>{{ plugin.name }}</strong><small>{{ plugin.status }}</small></span>
|
||||
<AppIcon :icon="Connection" /><span><strong>{{ plugin.name }}</strong><small>{{ plugin.status }}</small></span>
|
||||
</button>
|
||||
</div>
|
||||
<div v-else class="sidebar-list">
|
||||
<button v-for="skill in skillStore.skills" :key="skill.skill_id" class="sidebar-list-item extension-item"
|
||||
:class="{ active: skillStore.selectedSkillId === skill.skill_id }" @click="skillStore.selectSkill(skill.skill_id)">
|
||||
<span>{{ skill.icon || '⚡' }}</span><span><strong>{{ skill.name }}</strong><small>{{ skill.status }}</small></span>
|
||||
<AppIcon :icon="Lightning" /><span><strong>{{ skill.name }}</strong><small>{{ skill.status }}</small></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,21 +1,23 @@
|
||||
<script setup lang="ts">
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { computed, ref } from 'vue'
|
||||
import { ArrowLeftBold, ArrowRightBold, Brush, ChatDotRound, CircleCheck, Connection, Cpu, FolderOpened, Lightning, Search, Setting } from '@element-plus/icons-vue'
|
||||
import AppIcon from './AppIcon.vue'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const expanded = ref(localStorage.getItem('primary-sidebar-expanded') === 'true')
|
||||
|
||||
const navItems = [
|
||||
{ name: 'workspace', icon: '📁', label: '工作区' },
|
||||
{ name: 'search', icon: '🔍', label: '搜索' },
|
||||
{ name: 'chat', icon: '💬', label: 'AI 对话' },
|
||||
{ name: 'agent', icon: '🤖', label: 'Agent' },
|
||||
{ name: 'tasks', icon: '✅', label: '任务' },
|
||||
{ name: 'skills', icon: '⚡', label: 'Skill' },
|
||||
{ name: 'plugins', icon: '🧩', label: 'Plugin' },
|
||||
{ name: 'themes', icon: '🎨', label: '主题' },
|
||||
{ name: 'settings', icon: '⚙️', label: '设置' },
|
||||
{ name: 'workspace', icon: FolderOpened, label: '工作区' },
|
||||
{ name: 'search', icon: Search, label: '搜索' },
|
||||
{ name: 'chat', icon: ChatDotRound, label: 'AI 对话' },
|
||||
{ name: 'agent', icon: Cpu, label: 'Agent' },
|
||||
{ name: 'tasks', icon: CircleCheck, label: '任务' },
|
||||
{ name: 'skills', icon: Lightning, label: 'Skill' },
|
||||
{ name: 'plugins', icon: Connection, label: 'Plugin' },
|
||||
{ name: 'themes', icon: Brush, label: '主题' },
|
||||
{ name: 'settings', icon: Setting, label: '设置' },
|
||||
]
|
||||
|
||||
const currentName = computed(() => {
|
||||
@@ -43,13 +45,13 @@ function toggleExpanded() {
|
||||
@click="navigate(item.name)"
|
||||
:title="item.label"
|
||||
>
|
||||
<span class="nav-icon">{{ item.icon }}</span>
|
||||
<AppIcon class="nav-icon" :icon="item.icon" :size="20" />
|
||||
<span class="nav-label">{{ item.label }}</span>
|
||||
</div>
|
||||
</nav>
|
||||
<div class="sidebar-footer">
|
||||
<button class="nav-item collapse-button" type="button" :title="expanded ? '收起导航' : '展开导航'" @click="toggleExpanded">
|
||||
<span class="nav-icon">{{ expanded ? '«' : '»' }}</span>
|
||||
<AppIcon class="nav-icon" :icon="expanded ? ArrowLeftBold : ArrowRightBold" />
|
||||
<span class="nav-label">{{ expanded ? '收起' : '展开' }}</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -4,6 +4,8 @@ import { useRoute } from 'vue-router'
|
||||
import { useWorkspaceStore } from '@/stores/workspace'
|
||||
import { useEditorStore } from '@/stores/editor'
|
||||
import { useThemeStore } from '@/stores/theme'
|
||||
import { Moon, Sunny } from '@element-plus/icons-vue'
|
||||
import AppIcon from './AppIcon.vue'
|
||||
|
||||
const route = useRoute()
|
||||
const workspaceStore = useWorkspaceStore()
|
||||
@@ -52,7 +54,7 @@ const isDirty = computed(() => editorStore.saveStatus === 'dirty' || editorStore
|
||||
</div>
|
||||
<div class="titlebar-right">
|
||||
<button class="icon-btn" @click="themeStore.toggleTheme()" :title="themeStore.isDark ? '切换浅色主题' : '切换深色主题'">
|
||||
<span class="icon">{{ themeStore.isDark ? '☀️' : '🌙' }}</span>
|
||||
<AppIcon :icon="themeStore.isDark ? Sunny : Moon" :size="16" />
|
||||
</button>
|
||||
<div class="window-controls">
|
||||
<span class="win-btn minimize">—</span>
|
||||
|
||||
Reference in New Issue
Block a user