AppLayout
AppLayout 是完整的后台外壳:渐变顶栏(搜索、消息、通知、语言、颜色模式、用户菜单)、带激活路径的多级侧边菜单、用户资料、设置面板、页面标题和页脚。通过 config.layout 在 vertical、mini 和 horizontal 之间切换。
预览
<div class="layout-frame"><iframe src="http://localhost:5182/" title="Vue playground" loading="lazy"></iframe><p class="layout-frame__hint">Live Vue playground (run <code>npm run dev:vue</code>). Open the ⚙ settings panel to switch skin, layout, dark mode and language.</p></div>import { AppLayout, Page } from '@thl-ui/react';
import { Link, useLocation } from 'react-router';
<AppLayout menu={menu} currentPath={loc.pathname} user={{ ...user, onSelect: (k) => k === 'logout' && logout() }}
onSearch={(q) => nav(`/search?q=${q}`)}
renderLink={(item, children, className) => <Link to={item.href!} className={className}>{children}</Link>}
topbarRight={<TopbarMessages items={messages} icon="mail" />}
sidebarFooter={<Button variant="success" block>Upgrade</Button>}>
<Page title="Dashboard" breadcrumb={[{ label: 'Home', href: '/' }, { label: 'Dashboard' }]}>…</Page>
</AppLayout><thl-app-layout [menu]="menu" [currentPath]="path()" [user]="user" searchable (search)="search($event)" (userSelect)="onUser($event)">
<ng-template thlMenuLink let-item let-cls="cls" let-content="content">
<a [routerLink]="item.href" [class]="cls"><ng-container [ngTemplateOutlet]="content" /></a>
</ng-template>
<ng-container thlTopbarRight><thl-topbar-messages [items]="messages" icon="mail" /></ng-container>
<div thlSidebarFooter><button thl-button variant="success" block>Upgrade</button></div>
<router-outlet />
</thl-app-layout>Vue
<ThlAppLayout :menu="menu" :current-path="route.path" :user="user" searchable @search="onSearch" @user-select="onUser">
<template #topbar-right><ThlTopbarMessages :items="messages" icon="mail" /></template>
<template #link="{ item, content, class: cls }"><RouterLink :to="item.href" :class="cls"><component :is="() => content" /></RouterLink></template>
<template #sidebar-footer><ThlButton variant="success" block>升级</ThlButton></template>
<ThlPage title="Dashboard" :breadcrumb="[{ label: '首页', href: '/' }, { label: 'Dashboard' }]">…</ThlPage>
</ThlAppLayout>菜单
import type { MenuItem } from '@thl-ui/core';
export const menu: MenuItem[] = [
{ key: 'dash', label: 'menu.dashboard', icon: 'layout-dashboard', badge: { text: 4, color: 'danger' }, children: [
{ key: 'd1', label: 'menu.dashboard1', href: '/' },
{ key: 'd2', label: 'menu.dashboard2', href: '/dashboard-2' },
] },
{ key: 'h', label: 'menu.apps', heading: true },
{ key: 'inbox', label: 'menu.inbox', icon: 'mail', href: '/inbox' },
];label 可以是 i18n key(自动翻译)或普通字符串。激活路径根据 currentPath 计算。
横向布局
设置 layout: 'horizontal' 后,菜单从侧边移到顶栏下方的横条中(与 Cubic-horizontal 相同)。子菜单在鼠标悬停或键盘聚焦时以下拉方式展开。菜单始终保持一行:放不下的项目会收进 更多 下拉菜单,窗口变宽后再回到横条中。小于 768px 时恢复为普通的抽屉式侧边栏。同一个 menu 数组适用于所有布局。
// main.tsx: 以横向模式启动
<ThlProvider config={{ layout: 'horizontal' }}>
<AppLayout menu={menu} currentPath={loc.pathname} renderLink={renderLink}>…</AppLayout>
</ThlProvider>
// 运行时切换(⚙ 设置面板也是这样做的)
const [, setConfig] = useThlConfig();
setConfig({ layout: 'horizontal' });// main.ts: 以横向模式启动
app.use(ThlUI, { layout: 'horizontal' });
// 运行时切换(⚙ 设置面板也是这样做的)
const { set } = useThlConfig();
set({ layout: 'horizontal' });// main.ts: 以横向模式启动
bootstrapApplication(AppComponent, { providers: [provideThlUI({ layout: 'horizontal' })] });
// 运行时切换(⚙ 设置面板也是这样做的)
inject(ThlConfigService).set({ layout: 'horizontal' });在 playground 中试用:localhost:5182/?layout=horizontal。playground 还支持 ?layout=mini、?theme=red-dark、?lang=ja 和 ?mode=dark。
响应式行为
- ≥ 1170px:完整侧边栏(或根据
layout显示 mini / 横向) - 768 – 1169px:自动切换为 mini 侧边栏
- < 768px:带遮罩的抽屉式(off-canvas)侧边栏,从顶栏切换
断点可通过 components.Sidebar.breakpoint 配置。
API
AppLayout
<ThlAppLayout> · import { ThlAppLayout } from '@thl-ui/vue'
| Prop | 类型 | 默认值 |
|---|---|---|
menu* | array | — |
currentPath | string | — |
brand | string | "thl-ui" |
brandHref | string | "/" |
user | object | — |
searchable | boolean | — |
settings | boolean | true |
footer | string | boolean | — |
事件: searchuser-select
插槽: brandtopbar-lefttopbar-rightlinksidebar-footerdefaultfooter
SideMenu
<ThlSideMenu> · import { ThlSideMenu } from '@thl-ui/vue'
| Prop | 类型 | 默认值 |
|---|---|---|
items* | array | — |
currentPath | string | — |
accordion | boolean | true |
horizontal | boolean | — |
插槽: link
TopbarMessages
<ThlTopbarMessages> · import { ThlTopbarMessages } from '@thl-ui/vue'
| Prop | 类型 | 默认值 |
|---|---|---|
items* | array | — |
icon | string | "mail" |
title | string | — |
footer | string | — |
footerHref | string | — |
SettingsPanel
<ThlSettingsPanel> · import { ThlSettingsPanel } from '@thl-ui/vue'
| Prop | 类型 | 默认值 |
|---|---|---|
open | boolean | — |
事件: update:open
Page
<ThlPage> · import { ThlPage } from '@thl-ui/vue'
| Prop | 类型 | 默认值 |
|---|---|---|
title | string | — |
breadcrumb | array | — |
插槽: actionslinkdefault