feat(frontend): 统一界面图标体系

This commit is contained in:
2026-08-30 09:57:04 +08:00
parent bba3041867
commit c33610a295
14 changed files with 321 additions and 36 deletions
@@ -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>
+3 -1
View File
@@ -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>