185 lines
4.6 KiB
Vue
185 lines
4.6 KiB
Vue
<!-- 用户端侧栏,负责产品导航、品牌展示和账户入口。 -->
|
||
<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>
|