149 lines
3.9 KiB
Vue
149 lines
3.9 KiB
Vue
<template>
|
|
<div class="admin-layout">
|
|
<!-- 左侧菜单 -->
|
|
<a-menu
|
|
v-model:openKeys="state.openKeys"
|
|
v-model:selectedKeys="state.selectedKeys"
|
|
class="admin-sidebar"
|
|
:mode="state.mode"
|
|
:items="items"
|
|
:theme="state.theme"
|
|
@select="handleMenuSelect"
|
|
/>
|
|
<!-- 右侧内容区 -->
|
|
<div class="admin-contain">
|
|
<router-view />
|
|
</div>
|
|
</div>
|
|
</template>
|
|
<script lang="ts" setup>
|
|
import { h, reactive, computed } from 'vue';
|
|
import { useRouter } from 'vue-router';
|
|
import {
|
|
HomeOutlined,
|
|
FolderOpenOutlined,
|
|
ConsoleSqlOutlined,
|
|
GlobalOutlined,
|
|
LaptopOutlined,
|
|
MoneyCollectOutlined,
|
|
TeamOutlined,
|
|
} from '@ant-design/icons-vue';
|
|
import type { MenuMode, MenuTheme } from 'ant-design-vue';
|
|
import { ItemType } from 'ant-design-vue';
|
|
|
|
const router = useRouter();
|
|
|
|
// 定义菜单原始数据
|
|
interface MenuItem {
|
|
path: string;
|
|
name: string;
|
|
icon?: any;
|
|
children?: Omit<MenuItem, 'icon'>[]; // 子项不需要 icon
|
|
}
|
|
|
|
const menuItems: MenuItem[] = [
|
|
{ path: '/layout/admin/home', name: '总览', icon: HomeOutlined },
|
|
{ path: '/layout/admin/instance', name: '容器实例', icon: ConsoleSqlOutlined },
|
|
// { path: '/layout/admin/fileStore', name: '文件存储', icon: FolderOpenOutlined },
|
|
{ path: '/layout/admin/image', name: '镜像', icon: GlobalOutlined },
|
|
// { path: '/layout/publicData', name: '公开数据', icon: LaptopOutlined },
|
|
{
|
|
path: '',
|
|
name: '费用',
|
|
icon: MoneyCollectOutlined,
|
|
children: [
|
|
{ path: '/layout/admin/costDetail', name: '收支明细' },
|
|
{ path: '/layout/admin/myOrder', name: '我的订单' },
|
|
{ path: '/layout/admin/flow', name: '账单明细' },
|
|
{ path: '/layout/admin/coupon', name: '优惠券' },
|
|
{ path: '/layout/admin/invoice', name: '发票' },
|
|
{ path: '/layout/admin/voucher', name: '代金券' },
|
|
{ path: '/layout/admin/contract', name: '合同' },
|
|
],
|
|
},
|
|
{
|
|
path: '',
|
|
name: '账号',
|
|
icon: TeamOutlined,
|
|
children: [
|
|
{ path: '/layout/admin/security', name: '账号安全' },
|
|
{ path: '/layout/admin/history', name: '访问记录' },
|
|
// { path: '/controlPanel/security', name: '安全设置' },
|
|
],
|
|
},
|
|
];
|
|
|
|
// 状态
|
|
const state = reactive({
|
|
mode: 'inline' as MenuMode,
|
|
theme: 'light' as MenuTheme,
|
|
selectedKeys: ['/layout/admin/home'], // 初始选中第一个
|
|
openKeys: ['/controlPanel/fee', '/controlPanel/account'], // 默认展开有子菜单的项
|
|
});
|
|
|
|
// 工具函数:生成菜单项
|
|
function getItem(
|
|
label: string,
|
|
key: string,
|
|
icon?: any,
|
|
children?: ItemType[],
|
|
type?: 'group'
|
|
): ItemType {
|
|
return {
|
|
key,
|
|
icon,
|
|
children,
|
|
label,
|
|
type,
|
|
} as ItemType;
|
|
}
|
|
|
|
// 将 menuItems 转为 a-menu 所需的 items
|
|
const items = computed(() => {
|
|
return menuItems.map((item) => {
|
|
if (item.children && item.children.length > 0) {
|
|
const childItems = item.children.map((child) =>
|
|
getItem(child.name, child.path)
|
|
);
|
|
return getItem(item.name, item.path, h(item.icon), childItems);
|
|
} else {
|
|
return getItem(item.name, item.path, h(item.icon));
|
|
}
|
|
});
|
|
});
|
|
|
|
const handleMenuSelect = ({ key }: { key: string }) => {
|
|
console.log("11!",key);
|
|
router.push(key);
|
|
};
|
|
|
|
const changeMode = (checked: boolean) => {
|
|
state.mode = checked ? 'vertical' : 'inline';
|
|
};
|
|
|
|
const changeTheme = (checked: boolean) => {
|
|
state.theme = checked ? 'dark' : 'light';
|
|
};
|
|
</script>
|
|
|
|
<style scoped>
|
|
.admin-layout {
|
|
display: flex;
|
|
height: calc(100vh - 60px); /* 全屏高度 */
|
|
width: 100vw;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.admin-sidebar {
|
|
width: 256px; /* 和你原来设定一致 */
|
|
flex-shrink: 0; /* 防止被压缩 */
|
|
height: 100%;
|
|
}
|
|
|
|
.admin-contain {
|
|
flex: 1; /* 占据剩余空间 */
|
|
padding: 20px;
|
|
overflow-y: auto; /* 内容超出可滚动 */
|
|
background-color: #f0f2f5; /* 可选:和 Ant Design 风格一致 */
|
|
}
|
|
</style> |