优化左边栏的实现
This commit is contained in:
parent
35968bc93e
commit
569e4d3e45
@ -65,7 +65,7 @@ const MobileNav = defineAsyncComponent(
|
||||
const route = useRoute();
|
||||
const team = getTeam();
|
||||
|
||||
// Naive UI 主题配置 - 使用标准方式配置 tooltip
|
||||
// Naive UI 主题配置 - 使用标准方式配置 tooltip 和 menu
|
||||
const themeOverrides = {
|
||||
Tooltip: {
|
||||
color: '#fafafa',
|
||||
@ -73,8 +73,24 @@ const themeOverrides = {
|
||||
padding: '6px 12px',
|
||||
borderRadius: '8px',
|
||||
boxShadow: '0 2px 8px rgba(0, 0, 0, 0.08)',
|
||||
// 注意:Naive UI 的 theme-overrides 可能不直接支持箭头颜色
|
||||
// 箭头颜色需要通过 CSS 覆盖
|
||||
},
|
||||
Menu: {
|
||||
// 使用主题系统配置菜单样式,减少深度选择器
|
||||
itemTextColor: '#4a5568',
|
||||
itemTextColorHover: '#4a5568',
|
||||
itemTextColorActive: '#18a058',
|
||||
itemTextColorChildActive: '#18a058',
|
||||
itemColorHover: 'rgba(0, 0, 0, 0.04)',
|
||||
itemColorActive: 'rgba(24, 160, 88, 0.1)',
|
||||
itemColorActiveHover: 'rgba(24, 160, 88, 0.15)',
|
||||
itemBorderRadius: '8px',
|
||||
itemPadding: '10px 12px',
|
||||
itemIconColor: '#8b8e95',
|
||||
itemIconColorHover: '#18a058',
|
||||
itemIconColorActive: '#18a058',
|
||||
itemIconColorChildActive: '#18a058',
|
||||
itemIconSize: '18px',
|
||||
fontSize: '14px',
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@ -30,16 +30,16 @@
|
||||
<div class="sidebar-menu">
|
||||
<NavigationItems>
|
||||
<template v-slot="{ navigation }">
|
||||
<n-menu
|
||||
:collapsed="collapsed"
|
||||
:collapsed-width="64"
|
||||
:collapsed-icon-size="20"
|
||||
:options="convertToMenuOptions(navigation)"
|
||||
:value="activeKey"
|
||||
:router="false"
|
||||
@update:value="handleMenuSelect"
|
||||
class="app-sidebar-menu"
|
||||
/>
|
||||
<n-menu
|
||||
:collapsed="collapsed"
|
||||
:collapsed-width="64"
|
||||
:collapsed-icon-size="20"
|
||||
:options="convertToMenuOptions(navigation)"
|
||||
:value="activeKey"
|
||||
:router="false"
|
||||
@update:value="handleMenuSelect"
|
||||
class="app-sidebar-menu"
|
||||
/>
|
||||
</template>
|
||||
</NavigationItems>
|
||||
</div>
|
||||
@ -77,38 +77,14 @@ export default {
|
||||
},
|
||||
},
|
||||
emits: ['update:collapsed'],
|
||||
setup(props, { emit }) {
|
||||
setup(props) {
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const instance = getCurrentInstance();
|
||||
const showTeamSwitcher = ref(false);
|
||||
|
||||
// 响应式:在移动端默认折叠
|
||||
const isMobile = computed(() => {
|
||||
if (typeof window === 'undefined') return false;
|
||||
return window.innerWidth < 768;
|
||||
});
|
||||
|
||||
const collapsed = computed({
|
||||
get: () => {
|
||||
// 如果 props 有值,使用 props;否则根据屏幕大小判断
|
||||
if (props.collapsed !== undefined) {
|
||||
return props.collapsed;
|
||||
}
|
||||
return isMobile.value;
|
||||
},
|
||||
set: (value) => emit('update:collapsed', value),
|
||||
});
|
||||
|
||||
// 监听窗口大小变化
|
||||
if (typeof window !== 'undefined') {
|
||||
const handleResize = () => {
|
||||
if (window.innerWidth < 768 && !props.collapsed) {
|
||||
emit('update:collapsed', true);
|
||||
}
|
||||
};
|
||||
window.addEventListener('resize', handleResize);
|
||||
}
|
||||
// 简化:直接使用 props,响应式处理由父组件负责
|
||||
const collapsed = computed(() => props.collapsed);
|
||||
|
||||
// 下拉菜单选项
|
||||
const dropdownOptions = computed(() => {
|
||||
@ -155,29 +131,15 @@ export default {
|
||||
return items
|
||||
.filter((item) => item.condition !== false)
|
||||
.map((item) => {
|
||||
// 处理图标:item.icon 是一个函数,返回 h() 创建的组件
|
||||
// Naive UI 的 n-menu 需要 icon 是一个渲染函数
|
||||
// 处理图标:简化处理,直接使用渲染函数
|
||||
// Naive UI 的 NMenu 可以直接接受渲染函数作为 icon
|
||||
let iconComponent = undefined;
|
||||
if (item.icon) {
|
||||
iconComponent = () => {
|
||||
try {
|
||||
const iconVNode = item.icon();
|
||||
|
||||
// 如果图标 VNode 没有 props,添加默认的 size
|
||||
if (iconVNode && !iconVNode.props) {
|
||||
iconVNode.props = { width: 16, height: 16 };
|
||||
} else if (iconVNode && iconVNode.props) {
|
||||
// 确保有 size 属性
|
||||
if (!iconVNode.props.width && !iconVNode.props.size) {
|
||||
iconVNode.props.width = 16;
|
||||
}
|
||||
if (!iconVNode.props.height && !iconVNode.props.size) {
|
||||
iconVNode.props.height = 16;
|
||||
}
|
||||
}
|
||||
|
||||
// 用 NIcon 包装
|
||||
return h(NIcon, null, { default: () => iconVNode });
|
||||
// 用 NIcon 包装以保持样式一致性
|
||||
return h(NIcon, { size: 18 }, { default: () => iconVNode });
|
||||
} catch (e) {
|
||||
console.error(`[AppSidebar] Icon error for "${item.name}":`, e);
|
||||
return null;
|
||||
@ -233,14 +195,16 @@ export default {
|
||||
if (!path.startsWith('/')) {
|
||||
path = '/' + path;
|
||||
}
|
||||
// 如果路径是 /dashboard,转换为 /
|
||||
if (path === '/dashboard') {
|
||||
path = '/';
|
||||
// 如果路径是 /dashboard 或 /,统一处理
|
||||
if (path === '/dashboard' || path === '/') {
|
||||
return path;
|
||||
}
|
||||
return path;
|
||||
});
|
||||
|
||||
// 处理菜单选择
|
||||
// 注意:由于路由有 base 路径 '/dashboard/',不能使用 router="true"
|
||||
// 需要手动处理路由导航
|
||||
const handleMenuSelect = (key) => {
|
||||
// 路由配置的 base 是 '/dashboard/',key 已经是相对于 base 的路径(如 '/sites')
|
||||
// 直接使用 router.push,Vue Router 会自动处理 base
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user