117 lines
5.7 KiB
Vue
117 lines
5.7 KiB
Vue
<script setup>
|
|
import { computed } from "vue";
|
|
import { useRoute } from "vue-router";
|
|
import { useAuthStore } from "../stores/auth";
|
|
|
|
const route = useRoute();
|
|
const auth = useAuthStore();
|
|
|
|
const baseMenuItems = [
|
|
{ name: "home", label: "首页", to: "/", icon: "home" },
|
|
{ name: "avatar", label: "形象", to: "/avatar", icon: "avatar" },
|
|
{ name: "material", label: "素材", to: "/material", icon: "material" },
|
|
{ name: "voice", label: "声音", to: "/voice", icon: "voice" },
|
|
{ name: "compose", label: "合成", to: "/compose", icon: "compose" },
|
|
{ name: "extract", label: "提取", to: "/extract", icon: "extract" },
|
|
{ name: "design", label: "设计", to: "/design", icon: "design" },
|
|
{ name: "model", label: "模型", to: "/model", icon: "model" },
|
|
{ name: "local-config", label: "本地配置", to: "/local-config", icon: "settings" },
|
|
{ name: "help", label: "帮助", to: "/help", icon: "help" },
|
|
];
|
|
|
|
const menuItems = computed(() => {
|
|
const items = [...baseMenuItems];
|
|
if (auth.isAdmin) {
|
|
items.push({ name: "admin", label: "管理", to: "/admin", icon: "admin" });
|
|
}
|
|
if ( auth.isOEM) {
|
|
items.push({ name: "admin", label: "管理", to: "/oem", icon: "admin" });
|
|
}
|
|
if (auth.isAgent) {
|
|
items.push({ name: "agent", label: "代理", to: "/agent", icon: "agent" });
|
|
}
|
|
if (import.meta.env.DEV) {
|
|
items.push({ name: "debug", label: "调试", to: "/debug", icon: "debug" });
|
|
}
|
|
return items;
|
|
});
|
|
|
|
const activeName = computed(() => {
|
|
if (route.path.startsWith("/admin")) return "admin";
|
|
if (route.path.startsWith("/agent")) return "agent";
|
|
return route.name;
|
|
});
|
|
</script>
|
|
|
|
<template>
|
|
<nav class="sidebar-nav" aria-label="主导航">
|
|
<RouterLink
|
|
v-for="item in menuItems"
|
|
:key="item.name"
|
|
:to="item.to"
|
|
class="sidebar-item"
|
|
:class="{ 'sidebar-item--active': activeName === item.name }"
|
|
>
|
|
<span class="sidebar-icon" aria-hidden="true">
|
|
<svg v-if="item.icon === 'home'" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
|
|
<path d="M4 10.5 12 4l8 6.5V20a1 1 0 0 1-1 1h-5v-6H10v6H5a1 1 0 0 1-1-1v-9.5z" stroke-linejoin="round" />
|
|
</svg>
|
|
<svg v-else-if="item.icon === 'avatar'" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
|
|
<rect x="4" y="4" width="16" height="16" rx="3" />
|
|
<path d="M10 9.5v5l4-2.5-4-2.5z" fill="currentColor" stroke="none" />
|
|
</svg>
|
|
<svg v-else-if="item.icon === 'material'" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
|
|
<rect x="3" y="5" width="18" height="14" rx="2" />
|
|
<circle cx="8.5" cy="10" r="1.5" fill="currentColor" stroke="none" />
|
|
<path d="M3 16l5-4 4 3 5-5 4 4" />
|
|
</svg>
|
|
<svg v-else-if="item.icon === 'voice'" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
|
|
<path d="M12 4a3 3 0 0 1 3 3v5a3 3 0 0 1-6 0V7a3 3 0 0 1 3-3z" />
|
|
<path d="M6 11a6 6 0 0 0 12 0M12 17v3" />
|
|
</svg>
|
|
<svg v-else-if="item.icon === 'compose'" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
|
|
<rect x="3" y="6" width="18" height="12" rx="2" />
|
|
<path d="M7 6V4h10v2M10 12l2 1.5 2-1.5v-3l-2-1.5-2 1.5v3z" fill="currentColor" stroke="none" opacity="0.9" />
|
|
</svg>
|
|
<svg v-else-if="item.icon === 'extract'" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
|
|
<circle cx="6" cy="6" r="2.5" />
|
|
<circle cx="18" cy="18" r="2.5" />
|
|
<path d="M8 8l8 8M16 6l2 2M6 16l2 2" />
|
|
</svg>
|
|
<svg v-else-if="item.icon === 'design'" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
|
|
<path d="M14 4l6 6-10 10H4v-6L14 4z" stroke-linejoin="round" />
|
|
</svg>
|
|
<svg v-else-if="item.icon === 'model'" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
|
|
<path d="M12 3l7 4v10l-7 4-7-4V7l7-4z" />
|
|
<path d="M12 3v18M5 7l7 4 7-4" />
|
|
</svg>
|
|
<svg v-else-if="item.icon === 'settings'" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
|
|
<circle cx="12" cy="12" r="3" />
|
|
<path
|
|
d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M4.93 19.07l1.41-1.41M17.66 6.34l1.41-1.41"
|
|
stroke-linecap="round"
|
|
/>
|
|
</svg>
|
|
<svg v-else-if="item.icon === 'help'" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
|
|
<circle cx="12" cy="12" r="9" />
|
|
<path d="M9.5 9a2.5 2.5 0 1 1 4.2 1.8c-.8.7-1.2 1.2-1.2 2.2M12 17h.01" stroke-linecap="round" />
|
|
</svg>
|
|
<svg v-else-if="item.icon === 'admin'" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
|
|
<path d="M12 3l8 4v6c0 5-3.5 8-8 8s-8-3-8-8V7l8-4z" stroke-linejoin="round" />
|
|
<path d="M9 12l2 2 4-4" stroke-linecap="round" stroke-linejoin="round" />
|
|
</svg>
|
|
<svg v-else-if="item.icon === 'agent'" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
|
|
<circle cx="12" cy="8" r="3" />
|
|
<path d="M5 20c0-3.5 3-6 7-6s7 2.5 7 6" stroke-linecap="round" />
|
|
</svg>
|
|
<svg v-else-if="item.icon === 'debug'" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
|
|
<path d="M12 6v2M12 16v2M6 12h2M16 12h2" stroke-linecap="round" />
|
|
<circle cx="12" cy="12" r="4" />
|
|
<path d="M7 7l1.5 1.5M15.5 15.5L17 17M17 7l-1.5 1.5M8.5 15.5L7 17" stroke-linecap="round" />
|
|
</svg>
|
|
</span>
|
|
<span class="sidebar-label">{{ item.label }}</span>
|
|
</RouterLink>
|
|
</nav>
|
|
</template>
|