Files
JuYou/WEB/src/components/WebSidebar.vue
T
2026-08-25 17:59:42 +08:00

185 lines
4.6 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.
<!-- 用户端侧栏负责产品导航品牌展示和账户入口 -->
<script setup lang="ts">
import { Clapperboard, FileSearch, Film, Image, UserRound } from "@/icons";
import logoUrl from "@/assets/logo.png";
import WebUserEntry from "@/components/WebUserEntry.vue";
defineProps<{ activePath: string; collapsed?: boolean }>();
const emit = defineEmits<{ navigate: [path: string] }>();
const menus = [
{ path: "/drama-projects", label: "短剧创作", icon: Clapperboard, disabled: false },
{ path: "/redraw-projects", label: "剧本反推", icon: Film, disabled: false },
{ path: "/script-analysis", label: "剧本分析", icon: FileSearch, disabled: false },
{ path: "/product-images", label: "图片生成", icon: Image, disabled: false },
] as const;
</script>
<template>
<div
class="web-sidebar"
:class="{ 'is-collapsed': collapsed }"
>
<button
class="web-sidebar__brand"
type="button"
title="短剧创作"
@click="emit('navigate', '/drama-projects')"
>
<span
><img
:src="logoUrl"
alt=""
/></span>
<strong v-if="!collapsed">剧游AI</strong>
</button>
<nav class="web-sidebar__nav">
<button
v-for="item in menus"
:key="item.path"
type="button"
:disabled="item.disabled"
:class="{ active: activePath.startsWith(item.path) }"
:title="collapsed ? item.label : undefined"
@click="emit('navigate', item.path)"
>
<component
:is="item.icon"
:size="20"
/>
<span v-if="!collapsed">{{ item.label }}</span>
</button>
</nav>
<div class="web-sidebar__footer">
<button
v-if="collapsed"
type="button"
class="web-sidebar__account"
:class="{ active: activePath === '/account' }"
title="用户中心"
@click="emit('navigate', '/account')"
>
<UserRound :size="20" />
</button>
<WebUserEntry
v-else
:active="activePath === '/account'"
@navigate="emit('navigate', '/account')"
/>
</div>
</div>
</template>
<style scoped lang="scss">
.web-sidebar {
height: 100%;
padding: var(--space-lg) var(--space-md) var(--space-md);
display: flex;
flex-direction: column;
background: var(--web-sidebar);
border-right: 1px solid var(--web-line);
}
.web-sidebar__brand {
height: 48px;
padding: 0 var(--space-sm);
display: flex;
align-items: center;
gap: var(--space-md);
color: var(--web-text);
background: transparent;
border: 0;
cursor: pointer;
text-align: left;
border-radius: var(--radius-md);
transition: background-color 0.18s;
}
.web-sidebar__brand:hover {
background: var(--web-hover);
}
.web-sidebar__brand > span {
width: 36px;
height: 36px;
flex: 0 0 36px;
display: grid;
place-items: center;
overflow: hidden;
background: var(--web-surface);
border: 1px solid var(--web-line);
border-radius: var(--radius-sm);
}
.web-sidebar__brand img {
width: 32px;
height: 32px;
object-fit: contain;
}
.web-sidebar__brand strong {
display: flex;
flex-direction: column;
font-size: 17px;
font-weight: 650;
line-height: 1.2;
white-space: nowrap;
}
.web-sidebar__nav {
margin-top: var(--space-xl);
display: flex;
flex-direction: column;
gap: var(--space-xs);
}
.web-sidebar__nav button,
.web-sidebar__account {
min-height: 44px;
padding: 0 var(--space-md);
display: flex;
align-items: center;
gap: var(--space-md);
color: var(--web-muted);
background: transparent;
border: 1px solid transparent;
border-radius: var(--radius-md);
cursor: pointer;
transition:
background-color 0.18s,
color 0.18s,
border-color 0.18s;
}
.web-sidebar__nav button:hover:not(:disabled):not(.active),
.web-sidebar__account:hover:not(.active) {
color: var(--web-text);
background: var(--web-hover);
}
.web-sidebar__nav button:disabled {
color: var(--web-muted);
background: transparent;
cursor: not-allowed;
opacity: 0.55;
}
.web-sidebar__nav button.active,
.web-sidebar__account.active {
color: var(--web-brand-hover);
background: var(--web-brand-soft);
border-color: transparent;
font-weight: 600;
}
.web-sidebar__footer {
margin-top: auto;
padding-top: var(--space-md);
border-top: 1px solid var(--web-line);
}
.web-sidebar.is-collapsed {
padding-inline: var(--space-sm);
}
.web-sidebar.is-collapsed .web-sidebar__brand {
justify-content: center;
padding: 0;
}
.web-sidebar.is-collapsed .web-sidebar__nav button,
.web-sidebar.is-collapsed .web-sidebar__account {
width: 44px;
margin-inline: auto;
padding: 0;
justify-content: center;
}
</style>