PageGrid 页面栅格
用于承接 PC 页面级栅格规则。底层仍是 24 列;PageGrid 只负责区分后台管理和门户页两种页面场景,避免把侧边栏、门户边距和业务内容区混在一起算。
ts
import { createApp } from 'vue'
import { PageGrid, PageGridItem, PageLayout } from '@szhn/dh-design-pc'
const app = createApp({})
app.use(PageGrid)
app.use(PageGridItem)
app.use(PageLayout)PageGrid 通常放在页面最外层,先决定页面属于后台管理还是门户页;业务区域内部再使用 PageGridItem、PageLayout 或 Row / Col 承接具体内容。
页面最外层布局
<template>
<div ref="hostRef" class="page-shell-demo" :style="hostStyle">
<div ref="canvasRef" class="page-shell-demo__canvas" :style="canvasStyle">
<PageGrid scene="admin" sidebar="expanded" class="page-shell-demo__page">
<template #sidebar>
<nav class="page-shell-demo__sidebar">
<div class="page-shell-demo__sidebar-title">导航区</div>
<div v-for="item in menuItems" :key="item" class="page-shell-demo__menu-item">
{{ item }}
</div>
</nav>
</template>
<PageGridItem :span="24">
<header class="page-shell-demo__header">
<strong>任务管理</strong>
<span>页面标题区</span>
</header>
</PageGridItem>
<PageGridItem :span="24">
<section class="page-shell-demo__filter">筛选查询区</section>
</PageGridItem>
<PageGridItem :span="16">
<main class="page-shell-demo__main">任务列表区</main>
</PageGridItem>
<PageGridItem :span="8">
<aside class="page-shell-demo__aside">指标看板</aside>
</PageGridItem>
</PageGrid>
</div>
</div>
</template>
<script setup lang="ts">
import { PageGrid, PageGridItem } from '@szhn/dh-design-pc'
import { useScaledCanvas } from './useScaledCanvas'
const menuItems = ['工作台', '数据管理', '系统配置']
const { canvasRef, canvasStyle, hostRef, hostStyle } = useScaledCanvas()
</script>
<style scoped>
.page-shell-demo {
overflow: hidden;
position: relative;
width: 100%;
}
.page-shell-demo__canvas {
left: 0;
position: absolute;
top: 0;
transform-origin: left top;
}
.page-shell-demo__page {
background: var(--el-fill-color-lighter);
min-height: 420px;
padding-block: 16px;
}
.page-shell-demo__sidebar,
.page-shell-demo__header,
.page-shell-demo__filter,
.page-shell-demo__main,
.page-shell-demo__aside {
border: 1px solid var(--el-border-color-light);
}
.page-shell-demo__sidebar {
background: #e8ebef;
display: grid;
gap: 12px;
height: 388px;
padding: 16px;
}
.page-shell-demo__sidebar-title {
color: var(--el-text-color-secondary);
font-size: 13px;
font-weight: 600;
}
.page-shell-demo__menu-item {
align-items: center;
background: var(--el-bg-color);
color: var(--el-text-color-primary);
display: flex;
font-size: 13px;
height: 36px;
padding-inline: 12px;
}
.page-shell-demo__header {
align-items: center;
background: var(--el-bg-color);
display: flex;
gap: 12px;
height: 56px;
padding-inline: 16px;
}
.page-shell-demo__header span {
color: var(--el-text-color-secondary);
font-size: 13px;
}
.page-shell-demo__filter,
.page-shell-demo__main,
.page-shell-demo__aside {
align-items: center;
display: flex;
justify-content: center;
}
.page-shell-demo__filter {
background: var(--el-bg-color);
height: 72px;
}
.page-shell-demo__main {
background: var(--el-fill-color-light);
min-height: 220px;
}
.page-shell-demo__aside {
background: #e7eef8;
min-height: 220px;
}
</style>后台管理
<template>
<div ref="hostRef" class="page-grid-demo" :style="hostStyle">
<div ref="canvasRef" class="page-grid-demo__canvas" :style="canvasStyle">
<PageGrid scene="admin" sidebar="expanded" class="page-grid-demo__frame">
<template #sidebar>
<div class="page-grid-demo__sidebar">224px</div>
</template>
<PageGridItem v-for="item in 24" :key="`expanded-${item}`" :span="1">
<div class="page-grid-demo__col">34px</div>
</PageGridItem>
</PageGrid>
<PageGrid scene="admin" sidebar="collapsed" class="page-grid-demo__frame">
<template #sidebar>
<div class="page-grid-demo__sidebar page-grid-demo__sidebar--collapsed">80px</div>
</template>
<PageGridItem v-for="item in 24" :key="`collapsed-${item}`" :span="1">
<div class="page-grid-demo__col">40px</div>
</PageGridItem>
</PageGrid>
</div>
</div>
</template>
<script setup lang="ts">
import { PageGrid, PageGridItem } from '@szhn/dh-design-pc'
import { useScaledCanvas } from './useScaledCanvas'
const { canvasRef, canvasStyle, hostRef, hostStyle } = useScaledCanvas()
</script>
<style scoped>
.page-grid-demo {
overflow: hidden;
position: relative;
width: 100%;
}
.page-grid-demo__canvas {
display: grid;
gap: 24px;
left: 0;
position: absolute;
top: 0;
transform-origin: left top;
}
.page-grid-demo__frame {
background: var(--el-fill-color-light);
min-height: 112px;
padding-block: 16px;
}
.page-grid-demo__sidebar {
align-items: center;
background: #dfe3e8;
color: var(--el-text-color-secondary);
display: flex;
font-size: 12px;
height: 80px;
justify-content: center;
}
.page-grid-demo__sidebar--collapsed {
background: #e8ebef;
}
.page-grid-demo__col {
align-items: center;
background: rgb(7 90 237 / 12%);
color: var(--el-color-primary);
display: flex;
font-size: 11px;
height: 80px;
justify-content: center;
overflow: hidden;
white-space: nowrap;
}
</style>门户页
<template>
<div ref="hostRef" class="page-grid-portal-demo-shell" :style="hostStyle">
<div ref="canvasRef" class="page-grid-portal-demo-shell__canvas" :style="canvasStyle">
<PageGrid scene="portal" class="page-grid-portal-demo">
<PageGridItem :span="24">
<div class="page-grid-portal-demo__hero">1280px 内容区</div>
</PageGridItem>
<PageGridItem v-for="item in 4" :key="item" :span="6">
<div class="page-grid-portal-demo__card">6 列模块</div>
</PageGridItem>
</PageGrid>
</div>
</div>
</template>
<script setup lang="ts">
import { PageGrid, PageGridItem } from '@szhn/dh-design-pc'
import { useScaledCanvas } from './useScaledCanvas'
const { canvasRef, canvasStyle, hostRef, hostStyle } = useScaledCanvas()
</script>
<style scoped>
.page-grid-portal-demo-shell {
overflow: hidden;
position: relative;
width: 100%;
}
.page-grid-portal-demo-shell__canvas {
left: 0;
position: absolute;
top: 0;
transform-origin: left top;
}
.page-grid-portal-demo {
background: var(--el-fill-color-light);
padding-block: 20px;
}
.page-grid-portal-demo__hero,
.page-grid-portal-demo__card {
align-items: center;
background: var(--el-bg-color);
border: 1px solid var(--el-border-color-light);
color: var(--el-text-color-primary);
display: flex;
justify-content: center;
}
.page-grid-portal-demo__hero {
height: 96px;
font-size: 16px;
font-weight: 600;
}
.page-grid-portal-demo__card {
height: 72px;
font-size: 13px;
}
</style>页面分区
<template>
<div ref="hostRef" class="page-layout-demo-shell" :style="hostStyle">
<div ref="canvasRef" class="page-layout-demo" :style="canvasStyle">
<PageGrid scene="admin" sidebar="none">
<PageGridItem :span="24">
<PageLayout variant="t" side-width="180px" aside-width="220px">
<template #top>
<div class="page-layout-demo__block page-layout-demo__block--nav">导航栏</div>
</template>
<template #side>
<div class="page-layout-demo__block page-layout-demo__block--side">侧边栏</div>
</template>
<div class="page-layout-demo__block page-layout-demo__block--main">任务列表区</div>
<template #aside>
<div class="page-layout-demo__block page-layout-demo__block--aside">筛选查询区</div>
</template>
</PageLayout>
</PageGridItem>
</PageGrid>
<PageGrid scene="portal">
<PageGridItem :span="24">
<PageLayout variant="vertical">
<template #top>
<div class="page-layout-demo__block page-layout-demo__block--nav">一级导航栏</div>
</template>
<template #subtop>
<div class="page-layout-demo__block page-layout-demo__block--subnav">二级导航栏</div>
</template>
<div class="page-layout-demo__block page-layout-demo__block--main">主要内容区</div>
</PageLayout>
</PageGridItem>
</PageGrid>
</div>
</div>
</template>
<script setup lang="ts">
import { PageGrid, PageGridItem, PageLayout } from '@szhn/dh-design-pc'
import { useScaledCanvas } from './useScaledCanvas'
const { canvasRef, canvasStyle, hostRef, hostStyle } = useScaledCanvas()
</script>
<style scoped>
.page-layout-demo-shell {
overflow: hidden;
position: relative;
width: 100%;
}
.page-layout-demo {
display: grid;
gap: 20px;
left: 0;
position: absolute;
top: 0;
transform-origin: left top;
}
.page-layout-demo__block {
align-items: center;
border: 1px solid var(--el-border-color-light);
color: var(--el-text-color-primary);
display: flex;
font-size: 13px;
justify-content: center;
}
.page-layout-demo__block--nav,
.page-layout-demo__block--subnav {
background: rgb(7 90 237 / 14%);
height: 48px;
}
.page-layout-demo__block--side,
.page-layout-demo__block--aside {
background: #e7eef8;
height: 180px;
}
.page-layout-demo__block--main {
background: var(--el-fill-color-light);
min-height: 180px;
}
</style>规则
| 场景 | 外侧处理 | 内容区 | 栅格 |
|---|---|---|---|
| 后台管理 | 侧边栏是布局参数,不纳入栅格 | 右侧内容区流式自适应 | 24 列,默认 16px 水槽 |
| 门户页 | 1440px 基准下左右 80px,小屏不低于 24px | 最大 1280px,居中 | 24 列,默认 16px 水槽 |
后台页面不要套用门户页的 80px 边距,门户页面也不要使用后台的流式全宽规则。需要普通分栏时仍然可以直接使用 Row / Col。
API
PageGrid Props
| 属性名 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| scene | 页面场景 | admin / portal | admin |
| sidebar | 后台侧栏状态 | expanded / collapsed / none | none |
| columns | 栅格列数 | number | 24 |
| gutter | 水槽宽度 | string / number | var(--dh-grid-gutter, 16px) |
| row-gutter | 纵向间距 | string / number | var(--dh-grid-gutter, 16px) |
| admin-edge | 后台内容区边距 | string / number | var(--dh-content-margin, 16px) |
| admin-sidebar-width | 后台侧栏展开宽度 | string / number | var(--dh-sidebar-width, 224px) |
| admin-sidebar-collapsed-width | 后台侧栏收起宽度 | string / number | var(--dh-sidebar-collapsed-width, 80px) |
| portal-content-width | 门户内容区最大宽度 | string / number | 1280px |
| portal-edge | 门户基准边距 | string / number | 80px |
| portal-min-edge | 门户小屏最小边距 | string / number | 24px |
| grid | 是否把默认插槽作为 24 列栅格轨道 | boolean | true |
PageGrid Slots
| 插槽名 | 说明 |
|---|---|
| default | 内容区栅格项 |
| sidebar | 后台侧栏占位内容 |
PageGridItem Props
| 属性名 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| span | 占据列数 | number | 24 |
| offset | 左侧偏移列数 | number | 0 |
| columns | 当前总列数 | number | 24 |
PageLayout Props
| 属性名 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| variant | 内容区分区形态 | t / vertical | vertical |
| gap | 分区间距 | string / number | var(--dh-content-margin, 16px) |
| side-width | T 型布局左侧区域宽度 | string / number | 224px |
| aside-width | T 型布局右侧区域宽度 | string / number | 280px |
PageLayout Slots
| 插槽名 | 说明 |
|---|---|
| top | 顶部通栏 |
| subtop | 二级顶部区域 |
| default | 主内容区 |
| side | T 型布局左侧区域 |
| aside | T 型布局右侧区域 |
| bottom | 底部区域 |
