继续完善页面布局
This commit is contained in:
123
layouts/admin/components/AdminSubsider.uvue
Normal file
123
layouts/admin/components/AdminSubsider.uvue
Normal file
@@ -0,0 +1,123 @@
|
||||
<template>
|
||||
<view class="sub-sider" v-if="groups && groups.length > 0">
|
||||
<view class="sub-header">
|
||||
<text class="sub-title">{{ activeMenuTitle }}</text>
|
||||
<view class="sub-collapse" @click="collapsed = !collapsed">
|
||||
<text class="sub-collapse-text">{{ collapsed ? '›' : '‹' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<scroll-view class="sub-body" scroll-y="true">
|
||||
<view v-for="(g, gi) in groups" :key="gi" class="group">
|
||||
<view class="group-title" @click="toggleGroup(g.title)">
|
||||
<text class="group-title-text">{{ g.title }}</text>
|
||||
<text class="group-arrow">{{ isGroupOpen(g.title) ? '˄' : '˅' }}</text>
|
||||
</view>
|
||||
|
||||
<view v-if="isGroupOpen(g.title)">
|
||||
<view
|
||||
v-for="c in g.children"
|
||||
:key="c.id"
|
||||
class="sub-item"
|
||||
:class="{ active: activeSubId === c.id }"
|
||||
@click="$emit('sub-click', c)"
|
||||
>
|
||||
<text class="sub-item-text" :class="{ activeText: activeSubId === c.id }">
|
||||
{{ c.title }}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="uts">
|
||||
import { ref } from 'vue'
|
||||
import type { MenuGroup, MenuChild } from '../types.uts'
|
||||
|
||||
const props = defineProps<{
|
||||
activeMenuTitle: string
|
||||
groups: MenuGroup[]
|
||||
activeSubId: string
|
||||
}>()
|
||||
|
||||
defineEmits<{
|
||||
(e:'sub-click', child: MenuChild): void
|
||||
}>()
|
||||
|
||||
const collapsed = ref(false)
|
||||
const openGroups = ref<string[]>([])
|
||||
|
||||
const isGroupOpen = (title: string): boolean => {
|
||||
// 默认展开第一个分组 + 当前高亮分组(简单策略)
|
||||
if (openGroups.value.length === 0 && props.groups && props.groups.length > 0) return props.groups[0].title === title
|
||||
return openGroups.value.includes(title)
|
||||
}
|
||||
|
||||
const toggleGroup = (title: string) => {
|
||||
if (openGroups.value.includes(title)) {
|
||||
openGroups.value = openGroups.value.filter(t => t !== title)
|
||||
} else {
|
||||
openGroups.value = [...openGroups.value, title]
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.sub-sider{
|
||||
width: 240px;
|
||||
background:#ffffff;
|
||||
border-right: 1px solid #e5e7eb;
|
||||
height: 100vh;
|
||||
position: fixed;
|
||||
left: 96px; /* 紧贴主侧边栏 */
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
z-index: 900;
|
||||
}
|
||||
.sub-header{
|
||||
height: 56px;
|
||||
display:flex;
|
||||
align-items:center;
|
||||
justify-content: space-between;
|
||||
padding: 0 16px;
|
||||
border-bottom: 1px solid #eef2f7;
|
||||
}
|
||||
.sub-title{ font-size:16px; font-weight:600; color:#111827; }
|
||||
.sub-collapse{ width:28px; height:28px; display:flex; align-items:center; justify-content:center; }
|
||||
.sub-collapse-text{ color:#6b7280; }
|
||||
|
||||
.sub-body{ height: calc(100vh - 56px); }
|
||||
|
||||
.group{ padding: 8px 0; }
|
||||
.group-title{
|
||||
height: 44px;
|
||||
padding: 0 16px;
|
||||
display:flex;
|
||||
align-items:center;
|
||||
justify-content: space-between;
|
||||
color:#111827;
|
||||
}
|
||||
.group-title-text{ font-size:15px; font-weight:600; }
|
||||
.group-arrow{ color:#6b7280; }
|
||||
|
||||
.sub-item{
|
||||
height: 44px;
|
||||
padding: 0 16px;
|
||||
display:flex;
|
||||
align-items:center;
|
||||
background: transparent;
|
||||
}
|
||||
.sub-item.active{
|
||||
background: #eaf2ff;
|
||||
}
|
||||
.sub-item-text{
|
||||
font-size:14px;
|
||||
color:#111827;
|
||||
}
|
||||
.sub-item-text.activeText{
|
||||
color:#1677ff;
|
||||
font-weight:600;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user