BasicLayout 业务布局
@fx/layouts 业务层根布局组件。封装 FxLayout + slot 填业务组件(Sidebar/Header/Tabs/content/Footer)+ provide 业务上下文(menus/staticRoutes)+ route 变化加 tab + 首页解析 + 刷新完成 emit refreshed。多模式编排:读 setting 驱动 7 种布局模式,双列 / 混合状态机(useExtraMenu / useMixedMenu)自动接线,内置设置按钮(fixed 形态)+ 设置抽屉 + 页面切换动画 + 水印 + 移动端断点。消费方一行接入完整后台 layout。
基础用法
vue
<script setup lang="ts">
import { BasicLayout } from "@fx/layouts"
import { useUserStore } from "@/stores/user"
import { staticRoutes } from "@/router/static-routes"
import { resetDynamicRoutes } from "@/router"
import { APP_TITLE, SHOW_FOOTER, ICP, COPYRIGHT } from "@/utils"
import { useQueryCache } from "@pinia/colada"
const userStore = useUserStore()
async function handleLogout() {
await userStore.logout()
resetDynamicRoutes()
}
function onRefreshed() {
useQueryCache().invalidateQueries()
}
</script>
<template>
<BasicLayout
:title="APP_TITLE"
:menus="userStore.menus"
:static-routes="staticRoutes"
:user="userStore.user"
:show-footer="SHOW_FOOTER"
:icp="ICP"
:copyright="COPYRIGHT"
@logout="handleLogout"
@refreshed="onRefreshed"
/>
</template>首页默认按菜单
is_home标记 / 第一个可导航项自动解析。若需显式指定(如固定用/dashboard),加:home-path="'/dashboard'"。
Props
| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| title | 应用标题(Logo) | string | —(必填) |
| menus | 动态菜单树(来自 userStore.menus) | LayoutMenuNode[] | —(必填) |
| staticRoutes | 静态路由 | RouteRecordRaw[] | —(必填) |
| user | 当前用户 | LayoutUser | null | —(必填) |
| showFooter | 是否显示 footer(初值语义:无持久化 setting 时以此初始化,setting 优先) | boolean | false |
| icp | ICP 备案号 | string | — |
| copyright | 版权信息 | string | — |
| homePath | 显式首页路径(优先级 2,覆盖自动解析);不传则按菜单 is_home / 第一个可导航项自动解析 | string | — |
| watermarkContent | 水印内容(enableWatermark 开启时生效) | string | 应用标题 |
| showUser | 是否显示 header 用户区(头像 + 退出登录);无用户体系的消费方(如文档站)可关闭 | boolean | true |
| showNotify | 是否显示通知按钮;无通知体系的消费方可关闭 | boolean | true |
Events
| 事件名 | 说明 | 回调参数 |
|---|---|---|
| logout | 用户确认退出登录(消费方执行 userStore.logout + 路由重置) | () |
| refreshed | 刷新完成(refreshing true→false),消费方清缓存(如 useQueryCache) | () |
数据契约
menus / user 采用 layouts 视图模型(LayoutMenuNode / LayoutUser),仅含渲染所需字段。@fx/layouts 不依赖任何 @fx/api-* 包 —— 传任何结构兼容的对象即可,支持跨应用复用。
LayoutMenuNode
| 字段 | 类型 | 说明 |
|---|---|---|
| id | number | 菜单标识 |
| name | string | 显示名称 |
| path | string | null | 路由路径 |
| icon | string | null | 图标名(缺省回退默认占位图标 ep:list) |
| menu_type | 'directory' | 'menu' | 'button' | 分类(渲染三分模型) |
| children | LayoutMenuNode[] | 子菜单 |
| is_home | boolean | 是否为首页标记(命中则作为首页,优先级最高) |
| badge | string | 菜单项徽章文本(如 HTTP method 'GET');缺省不渲染,折叠态自动隐藏 |
| badgeColor | string | 徽章背景色(任意 CSS 色);缺省用 FxBadge 默认类型色 |
LayoutUser
| 字段 | 类型 | 说明 |
|---|---|---|
| username | string | 用户名 |
| nickname | string | null | 昵称 |
@fx/api-admin的MenuNode/SystemUser是上述视图模型的超集,结构子类型天然兼容,直接传入即可。
内部行为
- provide 业务上下文:menus / staticRoutes 经
provideLayoutBusiness注入,业务子组件(FxLayoutBreadcrumb / FxLayoutMenu / FxLayoutMenuSearch)inject 使用 - route 变化加 tab:watch route.path →
useLayoutStore.addTab(route) - 首页解析:watch menus / staticRoutes / homePath,按优先级(菜单
is_home>homePathprop > 第一个可导航项)解析首页,调useLayoutStore.setHome注入(store 不自行解析,因初始化时 menus 未到) - 菜单空状态:无任何可导航项且未传
homePath时,content 区渲染FxPageStatus(forbidden)显示"暂无菜单权限"提示 - 刷新解耦:
useLayoutStore.triggerRefresh()只切 refreshing;完成后 emitrefreshed,消费方监听清缓存(@fx/layouts不依赖@pinia/colada)
依赖
- 内部组合
FxLayoutSidebar/FxLayoutHeader/FxLayoutTabs/FxLayoutBreadcrumb/FxLayoutMenuSearch/FxLayoutMenu - 状态走
useLayoutStore(pinia)
