174 lines
5.1 KiB
TypeScript
174 lines
5.1 KiB
TypeScript
import { computed, defineComponent, ref } from 'vue';
|
||
import { Layout, Menu, Breadcrumb, Modal, Avatar, Space } from 'ant-design-vue';
|
||
import { RouterView, useRouter } from 'vue-router';
|
||
import {
|
||
MenuFoldOutlined,
|
||
MenuUnfoldOutlined,
|
||
ReloadOutlined,
|
||
SearchOutlined,
|
||
BellOutlined,
|
||
FullscreenOutlined,
|
||
UserOutlined,
|
||
} from '@ant-design/icons-vue';
|
||
import { useBasicLayout } from '../hooks/useBasicLayout';
|
||
import { auth } from '@/hooks/useAuth';
|
||
import styles from './BasicLayout.module.less';
|
||
|
||
// 解构 Layout 组件
|
||
const { Header, Sider, Content } = Layout;
|
||
|
||
/**
|
||
* 基础布局组件
|
||
*
|
||
* @description
|
||
* CPMS 运营平台的主布局结构,包含:
|
||
* - 左侧侧边栏:Logo + 导航菜单
|
||
* - 顶部 Header:菜单折叠按钮 + 面包屑 + 用户信息
|
||
* - 内容区域:路由视图渲染区域
|
||
*
|
||
* @example
|
||
* ```typescript
|
||
* // 在路由中使用
|
||
* {
|
||
* path: '/',
|
||
* component: BasicLayout,
|
||
* children: [...]
|
||
* }
|
||
* ```
|
||
*/
|
||
export default defineComponent({
|
||
name: 'BasicLayout',
|
||
setup() {
|
||
// 使用布局 Hook 获取菜单和面包屑数据
|
||
const { breadcrumbItems, menuItems, getActiveMenuKey, getOpenKeys, handleMenuClick } =
|
||
useBasicLayout();
|
||
|
||
// 路由实例,用于退出登录后跳转到登录页
|
||
const router = useRouter();
|
||
|
||
/**
|
||
* 侧边栏折叠状态
|
||
* true: 折叠状态(只显示图标)
|
||
* false: 展开状态(显示图标+文字)
|
||
*/
|
||
const collapsed = ref(false);
|
||
|
||
/**
|
||
* 切换侧边栏折叠/展开状态
|
||
*/
|
||
const toggleCollapsed = () => {
|
||
collapsed.value = !collapsed.value;
|
||
};
|
||
|
||
/**
|
||
* 退出登录:二次确认后跳转到登录页(不调用接口)
|
||
* - 点击用户名弹出确认弹框
|
||
* - 确定 -> 跳转登录页
|
||
* - 取消 -> 关闭弹框,不做任何处理
|
||
*/
|
||
const handleLogout = () => {
|
||
Modal.confirm({
|
||
title: '确认退出',
|
||
content: '确定要退出当前账号吗?',
|
||
okText: '确定',
|
||
cancelText: '取消',
|
||
onOk: () => {
|
||
// 清除本地登录态(不调用接口),否则路由守卫会把 /login 重定向回首页
|
||
auth.logout();
|
||
router.replace('/login');
|
||
},
|
||
});
|
||
};
|
||
|
||
return () => (
|
||
<Layout class={styles.container}>
|
||
{/* 左侧侧边栏 */}
|
||
<Sider
|
||
class={styles.sider}
|
||
collapsed={collapsed.value}
|
||
trigger={null}
|
||
collapsible
|
||
width={220}
|
||
>
|
||
{/* Logo 区域 */}
|
||
<div class={styles.logo}>
|
||
<div class={styles.logoIcon} />
|
||
<span class={styles.logoText}>{collapsed.value ? 'CPMS' : 'CPMS运营平台'}</span>
|
||
</div>
|
||
|
||
{/* 导航菜单 */}
|
||
<Menu
|
||
theme="light"
|
||
mode="inline"
|
||
selectedKeys={[getActiveMenuKey()]}
|
||
openKeys={getOpenKeys()}
|
||
items={menuItems}
|
||
onClick={handleMenuClick}
|
||
/>
|
||
</Sider>
|
||
|
||
{/* 右侧内容区域 */}
|
||
<Layout>
|
||
{/* 顶部 Header */}
|
||
<Header class={styles.header} style={{ background: '#ffffff' }}>
|
||
<div class={styles.headerLeft}>
|
||
{/* 折叠/展开按钮 */}
|
||
<span class={styles.trigger} onClick={toggleCollapsed}>
|
||
{collapsed.value ? <MenuUnfoldOutlined /> : <MenuFoldOutlined />}
|
||
</span>
|
||
|
||
{/* 刷新按钮 */}
|
||
{/* <span class={styles.refreshIcon}>
|
||
<ReloadOutlined />
|
||
</span> */}
|
||
|
||
{/* 面包屑导航 */}
|
||
{breadcrumbItems.value.length > 0 && (
|
||
<Breadcrumb class={styles.breadcrumb}>
|
||
{breadcrumbItems.value.map((item) => (
|
||
<Breadcrumb.Item key={item.key}>{item.title}</Breadcrumb.Item>
|
||
))}
|
||
</Breadcrumb>
|
||
)}
|
||
</div>
|
||
|
||
{/* Header 右侧:用户信息 */}
|
||
<div class={styles.headerRight}>
|
||
<Space size="middle">
|
||
{/* 搜索图标 */}
|
||
{/* <span class={styles.headerIcon}>
|
||
<SearchOutlined />
|
||
</span> */}
|
||
|
||
{/* 通知图标 */}
|
||
{/* <span class={styles.headerIcon}>
|
||
<BellOutlined />
|
||
</span> */}
|
||
|
||
{/* 全屏图标 */}
|
||
{/* <span class={styles.headerIcon}>
|
||
<FullscreenOutlined />
|
||
</span> */}
|
||
|
||
{/* 用户信息:点击弹出退出登录确认 */}
|
||
<div class={styles.userInfo} onClick={handleLogout}>
|
||
<Avatar size="small" icon={<UserOutlined />} />
|
||
<span class={styles.userName}>用户名</span>
|
||
</div>
|
||
</Space>
|
||
</div>
|
||
</Header>
|
||
|
||
{/* 内容区域 */}
|
||
<Content class={styles.content}>
|
||
<div class={styles.pageContent}>
|
||
{/* 路由视图:根据当前路由渲染对应页面 */}
|
||
<RouterView />
|
||
</div>
|
||
</Content>
|
||
</Layout>
|
||
</Layout>
|
||
);
|
||
},
|
||
});
|