Skip to content

布局组件

布局组件提供了构建页面结构的基础组件,包含过滤器、列表、表格、工具栏等常用的布局组件。

导入

typescript
import {
  DuxListLayout,
  DuxTableFilter,
  DuxTableLayout,
  DuxTableTools
} from '@duxweb/dvha-pro'

组件总览

DVHA Pro 提供以下布局组件:

  • DuxTableFilter - 表格过滤器组件
  • DuxTableTools - 表格工具栏组件
  • DuxListLayout - 列表布局组件
  • DuxTableLayout - 表格布局组件

DuxTableFilter 表格过滤器

表格过滤器组件,用于为表格提供筛选功能的布局容器。

属性

属性名类型默认值说明
labelstring''过滤器标签文本

插槽

插槽名说明
default过滤器内容

基础用法

vue
<script setup>
import { DuxTableFilter } from '@duxweb/dvha-pro'
import { ref } from 'vue'

const status = ref('')
const statusOptions = [
  { label: '全部', value: '' },
  { label: '启用', value: 'active' },
  { label: '禁用', value: 'inactive' }
]
</script>

<template>
  <DuxTableFilter label="状态">
    <n-select v-model:value="status" :options="statusOptions" />
  </DuxTableFilter>
</template>

DuxTableTools 表格工具栏

表格工具栏组件,当有选中项时显示在页面底部的操作工具栏。

属性

属性名类型默认值说明
numbernumber-选中项数量
optionsDuxToolOptionItem[]-工具选项
groupDuxToolOptionItem[][]-分组工具选项
dropdownDropdownOption[]-下拉菜单选项

DuxToolOptionItem 接口

typescript
interface DuxToolOptionItem {
  label?: string // 按钮文本
  icon?: string // 图标类名
  onClick?: () => void // 点击事件
  loading?: boolean // 加载状态
  disabled?: boolean // 禁用状态
  type?: 'default' | 'error' | 'success' | 'warning' // 按钮类型
}

基础用法

vue
<script setup>
import { DuxTableTools } from '@duxweb/dvha-pro'
import { ref } from 'vue'

const selectedCount = ref(3)

const toolGroups = [
  [
    {
      icon: 'i-tabler:x',
      onClick: () => {
        console.log('取消选择')
      },
    },
  ],
  [
    {
      label: '导出',
      icon: 'i-tabler:file-export',
      onClick: () => {
        console.log('导出选中项')
      },
    },
    {
      label: '删除',
      type: 'error',
      icon: 'i-tabler:trash',
      onClick: () => {
        console.log('删除选中项')
      },
    },
  ],
]
</script>

<template>
  <DuxTableTools
    :number="selectedCount"
    :group="toolGroups"
  />
</template>

DuxListLayout 列表布局

列表布局组件,提供标准的列表页面布局结构,包含筛选、分页、工具栏等功能。

属性

属性名类型默认值说明
rowKeystring'id'行键字段
pathstring-数据接口路径
filterRecord<string, any>-筛选条件
filterSchemaJsonSchemaNode[]-筛选表单配置
paginationboolean/objecttrue分页配置
tabsTabItem[]-标签页配置
toolsListPageTools-工具栏配置
actionsUseActionItem[][]操作配置
checkableboolean-是否支持选择
sideLeftTitlestring''左侧栏标题
sideRightTitlestring''右侧栏标题

接口定义

typescript
interface ListPageTools {
  import?: boolean // 是否显示导入按钮
  export?: boolean // 是否显示导出按钮
  refresh?: boolean // 是否显示刷新按钮
}

interface TabItem {
  label: string // 标签文本
  value: string | number // 标签值
}

插槽

插槽名说明参数
default列表内容result (列表数据结果)
actions操作按钮区域-
tools工具栏扩展-
bottom底部扩展区域-
sideLeft左侧栏内容-
sideRight右侧栏内容-

基础用法

vue
<script setup>
import { DuxListLayout } from '@duxweb/dvha-pro'
import { ref } from 'vue'

const filter = ref({})

const filterSchema = [
  {
    title: '名称',
    tag: 'NInput',
    attrs: {
      placeholder: '请输入名称',
    },
  },
  {
    title: '状态',
    tag: 'NSelect',
    attrs: {
      placeholder: '请选择状态',
      options: [
        { label: '全部', value: '' },
        { label: '启用', value: 'active' },
        { label: '禁用', value: 'inactive' }
      ]
    },
  },
]

const tabs = [
  { label: '全部', value: 'all' },
  { label: '已发布', value: 'published' },
  { label: '草稿', value: 'draft' },
]

const actions = [
  {
    label: '新增',
    icon: 'i-tabler:plus',
    onClick: () => {
      console.log('新增')
    }
  }
]
</script>

<template>
  <DuxListLayout
    path="/api/users"
    :filter="filter"
    :filter-schema="filterSchema"
    :tabs="tabs"
    :actions="actions"
    checkable
  >
    <template #default="{ list, isChecked, toggleChecked }">
      <div
        v-for="item in list"
        :key="item.id"
        class="p-4 border rounded-lg flex items-center gap-3"
      >
        <n-checkbox
          :checked="isChecked(item.id)"
          @update:checked="() => toggleChecked(item.id)"
        />
        <div>
          <h3>{{ item.name }}</h3>
          <p class="text-gray-500">
            {{ item.email }}
          </p>
        </div>
      </div>
    </template>
  </DuxListLayout>
</template>

DuxTableLayout 表格布局

表格布局组件,提供标准的表格页面布局结构,包含筛选、分页、列设置等功能。

属性

属性名类型默认值说明
pathstring-数据接口路径
filterRecord<string, any>-筛选条件
filterSchemaJsonSchemaNode[]-筛选表单配置
columnsTableColumn[]-表格列配置
paginationboolean/object-分页配置
tabsTabItem[]-标签页配置
actionsUseActionItem[][]操作配置
toolsTablePageTools-工具栏配置
sideLeftTitlestring''左侧栏标题
sideRightTitlestring''右侧栏标题

接口定义

typescript
interface TablePageTools {
  import?: boolean // 是否显示导入按钮
  export?: boolean // 是否显示导出按钮
  refresh?: boolean // 是否显示刷新按钮
}

插槽

插槽名说明参数
default表格内容result (表格数据和配置结果)
actions操作按钮区域-
tools工具栏扩展-
bottom底部扩展区域-
sideLeft左侧栏内容-
sideRight右侧栏内容-

基础用法

vue
<script setup>
import { DuxTableLayout } from '@duxweb/dvha-pro'
import { ref } from 'vue'

const filter = ref({})

const filterSchema = [
  {
    title: '用户名',
    tag: 'NInput',
    attrs: {
      placeholder: '请输入用户名',
    },
  },
  {
    title: '状态',
    tag: 'NSelect',
    attrs: {
      placeholder: '请选择状态',
      options: [
        { label: '全部', value: '' },
        { label: '启用', value: 'active' },
        { label: '禁用', value: 'inactive' }
      ]
    },
  },
]

const columns = [
  {
    key: 'id',
    title: 'ID',
    width: 80,
  },
  {
    key: 'name',
    title: '姓名',
    width: 120,
  },
  {
    key: 'email',
    title: '邮箱',
    width: 200,
  },
  {
    key: 'status',
    title: '状态',
    width: 100,
    render: (row) => {
      return row.status === 'active' ? '启用' : '禁用'
    }
  },
]

const actions = [
  {
    label: '新增用户',
    icon: 'i-tabler:plus',
    onClick: () => {
      console.log('新增用户')
    }
  }
]
</script>

<template>
  <DuxTableLayout
    path="/api/users"
    :filter="filter"
    :filter-schema="filterSchema"
    :columns="columns"
    :actions="actions"
  >
    <template #default="{ table, width }">
      <n-data-table
        remote
        class="h-full"
        :min-height="200"
        table-layout="fixed"
        flex-height
        :row-key="row => row.id"
        :bordered="false"
        :scroll-x="width"
        v-bind="table"
      />
    </template>
  </DuxTableLayout>
</template>

完整示例

带侧边栏的表格页面

vue
<script setup>
import { DuxTableLayout } from '@duxweb/dvha-pro'
import { ref } from 'vue'

const filter = ref({})
const selectedCategory = ref(null)

const filterSchema = [
  {
    title: '标题',
    tag: 'NInput',
    attrs: {
      placeholder: '请输入文章标题',
    },
  },
]

const columns = [
  { key: 'id', title: 'ID', width: 80 },
  { key: 'title', title: '标题', width: 200 },
  { key: 'category', title: '分类', width: 120 },
  { key: 'created_at', title: '创建时间', width: 160 },
]

const categories = [
  { id: 1, name: '技术文章' },
  { id: 2, name: '产品介绍' },
  { id: 3, name: '行业资讯' },
]

function handleCategorySelect(categoryId) {
  selectedCategory.value = categoryId
  filter.value.category_id = categoryId
}
</script>

<template>
  <DuxTableLayout
    path="/api/articles"
    :filter="filter"
    :filter-schema="filterSchema"
    :columns="columns"
    side-left-title="文章分类"
  >
    <!-- 主表格内容 -->
    <template #default="{ table, width }">
      <n-data-table
        remote
        class="h-full"
        :min-height="200"
        table-layout="fixed"
        flex-height
        :row-key="row => row.id"
        :bordered="false"
        :scroll-x="width"
        v-bind="table"
      />
    </template>

    <!-- 左侧栏:分类列表 -->
    <template #sideLeft>
      <div class="p-4">
        <h3 class="text-lg font-semibold mb-4">
          文章分类
        </h3>
        <div class="space-y-2">
          <div
            v-for="category in categories"
            :key="category.id"
            class="p-2 rounded cursor-pointer hover:bg-gray-100"
            :class="{ 'bg-blue-50 text-blue-600': selectedCategory === category.id }"
            @click="handleCategorySelect(category.id)"
          >
            {{ category.name }}
          </div>
        </div>
      </div>
    </template>

    <!-- 工具栏扩展 -->
    <template #tools>
      <n-button secondary>
        <template #icon>
          <div class="i-tabler:refresh" />
        </template>
        刷新
      </n-button>
    </template>
  </DuxTableLayout>
</template>

响应式支持

所有布局组件都支持响应式设计:

  • 桌面端 (≥1024px): 显示完整布局,包含侧边栏
  • 平板端 (768px-1023px): 自适应布局,部分元素调整
  • 移动端 (<768px): 侧边栏转为抽屉模式,简化分页组件

相关文档