You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
151 lines
3.8 KiB
Plaintext
151 lines
3.8 KiB
Plaintext
11 months ago
|
<script lang="tsx">
|
||
|
import { defineComponent, ref } from 'vue'
|
||
|
import {
|
||
|
Layout,
|
||
|
LayoutSider,
|
||
|
Menu,
|
||
|
SubMenu,
|
||
|
MenuItem,
|
||
|
LayoutHeader,
|
||
|
LayoutContent
|
||
|
} from 'ant-design-vue'
|
||
|
import { RouterView, type RouteRecordRaw, useRouter } from 'vue-router'
|
||
|
import LogoCollapsePic from '@/assets/logo_collapse.png'
|
||
|
import LogoNormalPic from '@/assets/logo.png'
|
||
|
import { MenuUnfoldOutlined, MenuFoldOutlined } from '@ant-design/icons-vue'
|
||
|
import { menuRoutes } from '@/router'
|
||
|
import UserDropdownVue from '@/components/UserDropdown.vue'
|
||
|
|
||
|
export default defineComponent({
|
||
|
name: 'index-page',
|
||
|
setup() {
|
||
|
const collapsed = ref(false)
|
||
|
const selectedKeys = ref<string[]>([])
|
||
|
const router = useRouter()
|
||
|
const renderMenuItem = (item: RouteRecordRaw) => {
|
||
|
const meta = item.meta as any
|
||
|
if (!meta) return <p>请配置meta参数</p>
|
||
|
if (Array.isArray(item.children) && item.children.length > 0) {
|
||
|
return (
|
||
|
<SubMenu
|
||
|
key={item.path}
|
||
|
v-slots={{
|
||
|
title: () => meta.label,
|
||
|
icon: () => <meta.icon />
|
||
|
}}
|
||
|
>
|
||
|
{item.children?.map((child) => {
|
||
|
const cMeta = child.meta as any
|
||
|
if (!meta) return <p>请配置meta参数</p>
|
||
|
return (
|
||
|
<MenuItem
|
||
|
key={item.path + '/' + child.path}
|
||
|
v-slots={{
|
||
|
icon: () => <cMeta.icon />
|
||
|
}}
|
||
|
>
|
||
|
{cMeta.label}
|
||
|
</MenuItem>
|
||
|
)
|
||
|
})}
|
||
|
</SubMenu>
|
||
|
)
|
||
|
}
|
||
|
return (
|
||
|
<MenuItem key={item.path}>
|
||
|
<meta.icon />
|
||
|
{meta.label}
|
||
|
</MenuItem>
|
||
|
)
|
||
|
}
|
||
|
|
||
|
const onMenuSelect = (item: any) => {
|
||
|
router.push(item.key)
|
||
|
}
|
||
|
return () => (
|
||
|
<Layout style={{ height: '100vh' }}>
|
||
|
<LayoutSider v-model:collapsed={collapsed.value} trigger={null} collapsible>
|
||
|
<div class="logo">
|
||
|
<img src={collapsed.value ? LogoCollapsePic : LogoNormalPic} alt="logo" />
|
||
|
</div>
|
||
|
<Menu
|
||
|
v-model:selectedKeys={selectedKeys.value}
|
||
|
theme="dark"
|
||
|
mode="inline"
|
||
|
onSelect={onMenuSelect}
|
||
|
>
|
||
|
{menuRoutes.map((menu) => renderMenuItem(menu))}
|
||
|
</Menu>
|
||
|
</LayoutSider>
|
||
|
<Layout>
|
||
|
<LayoutHeader style={{ background: '#fff', padding: 0 }}>
|
||
|
<div class="header-content">
|
||
|
{collapsed.value ? (
|
||
|
<MenuUnfoldOutlined
|
||
|
class="trigger"
|
||
|
onClick={() => (collapsed.value = !collapsed.value)}
|
||
|
/>
|
||
|
) : (
|
||
|
<MenuFoldOutlined
|
||
|
class="trigger"
|
||
|
onClick={() => (collapsed.value = !collapsed.value)}
|
||
|
/>
|
||
|
)}
|
||
|
<UserDropdownVue />
|
||
|
</div>
|
||
|
</LayoutHeader>
|
||
|
<LayoutContent
|
||
|
style={{
|
||
|
margin: '24px 16px',
|
||
|
padding: '24px',
|
||
|
background: '#fff',
|
||
|
minHeight: '280px'
|
||
|
}}
|
||
|
>
|
||
|
<RouterView />
|
||
|
</LayoutContent>
|
||
|
</Layout>
|
||
|
</Layout>
|
||
|
)
|
||
|
}
|
||
|
})
|
||
|
</script>
|
||
|
|
||
|
<style lang="less" scoped>
|
||
|
.logo {
|
||
|
height: 64px;
|
||
|
color: white;
|
||
|
display: flex;
|
||
|
align-items: center;
|
||
|
justify-content: center;
|
||
|
|
||
|
img {
|
||
|
height: 40px;
|
||
|
object-fit: contain;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
.header-content {
|
||
|
display: flex;
|
||
|
align-items: center;
|
||
|
justify-content: space-between;
|
||
|
box-sizing: border-box;
|
||
|
padding-right: 24px;
|
||
|
}
|
||
|
|
||
|
:deep(.trigger) {
|
||
|
font-size: 18px;
|
||
|
line-height: 64px;
|
||
|
padding: 0 24px;
|
||
|
cursor: pointer;
|
||
|
transition: color 0.3s;
|
||
|
&:hover {
|
||
|
color: #1890ff;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
.site-layout .site-layout-background {
|
||
|
background: #fff;
|
||
|
}
|
||
|
</style>
|