cpms_operation_platform/src/layouts/BasicLayout.tsx

174 lines
5.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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>
);
},
});