初始化

This commit is contained in:
Ran
2026-08-25 17:59:42 +08:00
commit 4b7380dd9b
408 changed files with 327400 additions and 0 deletions
+184
View File
@@ -0,0 +1,184 @@
<!-- 用户端侧栏负责产品导航品牌展示和账户入口 -->
<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>