- Updated Container.vue to import SubNavItem from Secondary.vue and renamed component usage. - Removed NavMain.vue and NavUser.vue components, consolidating sidebar functionality. - Deleted Sidebar.vue and created a new sidebar structure in index.vue. - Implemented new Main.vue and User.vue components under sidebar/nav for better organization. - Added DPlayer for video playback in preview page and adjusted layout accordingly. - Introduced new course Card.vue component for displaying course information. - Created Secondary.vue for secondary navigation with improved styling and functionality. - Updated package.json to include dplayer and its types for video handling.
127 lines
3.7 KiB
Vue
127 lines
3.7 KiB
Vue
<script setup lang="ts">
|
|
import { ChevronRight } from 'lucide-vue-next'
|
|
import type { SidebarNavItem } from './Sidebar.vue'
|
|
|
|
defineProps<{
|
|
nav: {
|
|
label?: string
|
|
items: SidebarNavItem[]
|
|
}[]
|
|
}>()
|
|
</script>
|
|
|
|
<template>
|
|
<SidebarGroup
|
|
v-for="group in nav"
|
|
:key="group.label"
|
|
>
|
|
<SidebarGroupLabel v-if="group.label">
|
|
{{ group.label }}
|
|
</SidebarGroupLabel>
|
|
<SidebarMenu>
|
|
<Collapsible
|
|
v-for="item in group.items"
|
|
:key="item.title"
|
|
as-child
|
|
:default-open="item.isActive"
|
|
class="group/collapsible"
|
|
>
|
|
<SidebarMenuItem>
|
|
<CollapsibleTrigger as-child>
|
|
<!-- 有跳转链接 -->
|
|
<NuxtLink
|
|
v-if="item.url"
|
|
v-slot="{ isActive, href, navigate }"
|
|
class="py-5"
|
|
:to="item.url"
|
|
custom
|
|
>
|
|
<SidebarMenuButton
|
|
as="a"
|
|
:tooltip="item.title"
|
|
:is-active="isActive"
|
|
:href
|
|
:target="item.isExternal ? '_blank' : undefined"
|
|
@click="navigate"
|
|
>
|
|
<!-- 图标名 -->
|
|
<Icon
|
|
v-if="item.icon && typeof item.icon === 'string'"
|
|
:name="item.icon"
|
|
class="!size-6"
|
|
/>
|
|
<!-- 图标组件 -->
|
|
<component
|
|
:is="item.icon"
|
|
v-else
|
|
class="!size-6"
|
|
/>
|
|
<span>{{ item.title }}</span>
|
|
<!-- 有子项目 -->
|
|
<ChevronRight
|
|
v-if="item.items"
|
|
class="ml-auto transition-transform duration-200 group-data-[state=open]/collapsible:rotate-90"
|
|
/>
|
|
<!-- 外部链接 -->
|
|
<Icon
|
|
v-if="item.isExternal"
|
|
name="tabler:external-link"
|
|
class="ml-auto !size-4 opacity-50"
|
|
size="16px"
|
|
/>
|
|
</SidebarMenuButton>
|
|
</NuxtLink>
|
|
<!-- 无跳转链接 -->
|
|
<SidebarMenuButton
|
|
v-else
|
|
:tooltip="item.title"
|
|
>
|
|
<!-- 图标名 -->
|
|
<Icon
|
|
v-if="item.icon && typeof item.icon === 'string'"
|
|
:name="item.icon"
|
|
size="16px"
|
|
/>
|
|
<!-- 图标组件 -->
|
|
<component
|
|
:is="item.icon"
|
|
v-else
|
|
/>
|
|
<span>{{ item.title }}</span>
|
|
<ChevronRight
|
|
v-if="item.items"
|
|
class="ml-auto transition-transform duration-200 group-data-[state=open]/collapsible:rotate-90"
|
|
/>
|
|
</SidebarMenuButton>
|
|
</CollapsibleTrigger>
|
|
|
|
<CollapsibleContent v-if="item.items">
|
|
<SidebarMenuSub>
|
|
<SidebarMenuSubItem
|
|
v-for="subItem in item.items"
|
|
:key="subItem.title"
|
|
>
|
|
<NuxtLink
|
|
v-slot="{ isActive, href, navigate }"
|
|
:to="subItem.url"
|
|
custom
|
|
>
|
|
<SidebarMenuSubButton
|
|
as="a"
|
|
as-child
|
|
:is-active="isActive"
|
|
:href
|
|
@click="navigate"
|
|
>
|
|
<span>{{ subItem.title }}</span>
|
|
</SidebarMenuSubButton>
|
|
</NuxtLink>
|
|
</SidebarMenuSubItem>
|
|
</SidebarMenuSub>
|
|
</CollapsibleContent>
|
|
</SidebarMenuItem>
|
|
</Collapsible>
|
|
</SidebarMenu>
|
|
</SidebarGroup>
|
|
</template>
|