Skip to content

ProPage 页面骨架

基于 plus-pro-components / Page 的 dh-design-pc 页面级封装,适合“筛选表单 + 表格 + 分页 + 工具栏”的标准业务列表页。

当前组件支持两种模式:

  1. 基础模式:业务方自行传入 search-model / data / total / page / page-size
  2. request 模式:通过 requestparamsbefore-search-submit 管理整页数据流

ProPage 会把分页区域稳定放在表格可视区底部;表格内容出现纵向滚动时,分页不会跟着滚出视线。需要关闭时传 sticky-pagination="false"

ProPage 默认使用 PC 端业务列表规范:表格常规密度、空值使用 -、单元格单行省略、最小表格宽度 960px、操作列最多平铺 3 项。业务方可通过 table 属性覆盖这些默认值。

ts
import { createApp } from 'vue'
import { ProPage } from '@szhn/dh-design-pc'

const app = createApp({})
app.use(ProPage)

基础用法

<template>
  <dh-pro-page
    v-model:search-model="searchModel"
    :columns="columns"
    :request="requestAssetList"
  >
    <template #search-toolbar>
      <el-button type="primary">添加成员</el-button>
      <el-button>导入</el-button>
      <el-button>导出花名册</el-button>
      <el-button disabled>批量删除</el-button>
      <el-input placeholder="请输入文字" style="width: 200px" />
    </template>
  </dh-pro-page>
</template>

<script lang="ts" setup>
import { ref } from 'vue'
import { pageColumns, requestAssetList } from './shared'

const searchModel = ref<Record<string, any>>({})
const columns = pageColumns
</script>

手动控制搜索值

<template>
  <div class="pro-page-demo">
    <div class="pro-page-demo__actions">
      <el-button type="primary" @click="setName">设置名称</el-button>
      <el-button @click="setStatus">设置状态</el-button>
      <el-button @click="logName">获取名称</el-button>
      <el-button @click="clearFields">清空搜索项</el-button>
    </div>
    <dh-pro-page
      ref="pageRef"
      :columns="pageColumns"
      :request="requestAssetList"
      :search="{ showNumber: 2 }"
    />
  </div>
</template>

<script lang="ts" setup>
import { ref } from 'vue'
import { pageColumns, requestAssetList } from './shared'

const pageRef = ref<any>(null)

const setName = () => pageRef.value?.setSearchFieldsValue?.({ name: '2name' })
const setStatus = () => pageRef.value?.setSearchFieldsValue?.({ status: '1' })
const logName = () => console.log(pageRef.value?.getSearchFieldsValue?.('name'))
const clearFields = () => pageRef.value?.clearSearchFieldsValue?.()
</script>

<style scoped>
.pro-page-demo {
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.pro-page-demo__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
}
</style>

搜索参数处理

<template>
  <div class="pro-page-demo">
    <el-alert title="打开控制台可看到 beforeSearchSubmit 转换后的查询参数。" type="info" :closable="false" />
    <dh-pro-page
      :columns="pageColumns"
      :request="requestAssetList"
      :search="{ showNumber: 2 }"
      :before-search-submit="beforeSearchSubmit"
    />
  </div>
</template>

<script lang="ts" setup>
import { pageColumns, requestAssetList } from './shared'

const beforeSearchSubmit = (values: Record<string, any>) => {
  const payload = {
    assetName: values.name,
    assetStatus: values.status,
  }
  console.log('beforeSearchSubmit', payload)
  return payload
}
</script>

<style scoped>
.pro-page-demo {
  display: flex;
  flex-direction: column;
  gap: 12px;
}
</style>

默认搜索参数

<template>
  <dh-pro-page
    :columns="pageColumns"
    :request="requestAssetList"
    :search="{
      showNumber: 2,
      defaultValues: {
        status: '1',
        name: '1name',
      },
    }"
  />
</template>

<script lang="ts" setup>
import { pageColumns, requestAssetList } from './shared'
</script>

默认分页参数

<template>
  <dh-pro-page
    :columns="pageColumns"
    :request="requestAssetList"
    :search="{ showNumber: 2 }"
    :default-page-info="{ page: 2, pageSize: 5 }"
  />
</template>

<script lang="ts" setup>
import { pageColumns, requestAssetList } from './shared'
</script>

自定义搜索按钮

<template>
  <dh-pro-page :columns="pageColumns" :request="requestAssetList" :search="{ showNumber: 2 }">
    <template #search-footer="{ handleReset, handleSearch, handleUnfold, isShowUnfold }">
      <div class="pro-page-footer">
        <el-button type="primary" @click="handleSearch">搜索</el-button>
        <el-button @click="handleReset">重置</el-button>
        <el-button @click="handleUnfold">{{ isShowUnfold ? '收起' : '展开' }}</el-button>
      </div>
    </template>
  </dh-pro-page>
</template>

<script lang="ts" setup>
import { pageColumns, requestAssetList } from './shared'
</script>

<style scoped>
.pro-page-footer {
  display: flex;
  gap: 12px;
}
</style>

自定义搜索表单插槽

<template>
  <dh-pro-page
    v-model:search-model="searchModel"
    :columns="pageColumns"
    :request="requestAssetList"
    :search="{ showNumber: 2 }"
    search-slot
  >
    <template #plus-field-name="{ prop, column }">
      <el-input
        :model-value="searchModel[prop]"
        :placeholder="`自定义 ${column.label}`"
        @update:model-value="updateSearchModel(prop, $event)"
      />
    </template>
    <template #plus-label-name="{ label }">
      <span class="pro-page-label">{{ label }}(自定义)</span>
    </template>
  </dh-pro-page>
</template>

<script lang="ts" setup>
import { ref } from 'vue'
import { pageColumns, requestAssetList } from './shared'

const searchModel = ref<Record<string, any>>({})

const updateSearchModel = (prop: string, value: string) => {
  searchModel.value[prop] = value
}
</script>

<style scoped>
.pro-page-label {
  color: var(--el-color-primary);
  font-weight: 600;
}
</style>

搜索和表格展示顺序控制

<template>
  <dh-pro-page
    :columns="columns"
    :request="requestAssetList"
    :search="{ showNumber: 2 }"
  />
</template>

<script lang="ts" setup>
import type { PcProColumn } from '@szhn/dh-design-pc'
import { pageColumns, requestAssetList } from './shared'

const columns: PcProColumn[] = pageColumns.map(column => {
  if (column.prop === 'name') return { ...column, search: { order: 2 } }
  if (column.prop === 'status') return { ...column, search: { order: 3 } }
  if (column.prop === 'time') return { ...column, search: { order: 1 } }
  return column
})
</script>

model-value / v-model

<template>
  <div class="pro-page-demo">
    <el-button @click="setExternalValues">通过外部 model 更新筛选项</el-button>
    <dh-pro-page
      v-model:search-model="searchModel"
      :columns="pageColumns"
      :request="requestAssetList"
      :search="{ showNumber: 2 }"
    />
  </div>
</template>

<script lang="ts" setup>
import { ref } from 'vue'
import { pageColumns, requestAssetList } from './shared'

const searchModel = ref<Record<string, any>>({
  status: '0',
})

const setExternalValues = () => {
  searchModel.value = {
    ...searchModel.value,
    name: '3name',
    status: '2',
  }
}
</script>

<style scoped>
.pro-page-demo {
  display: flex;
  flex-direction: column;
  gap: 16px;
}
</style>

增删改查(CRUD)

<template>
  <div class="pro-page-demo">
    <dh-pro-page
      :columns="pageColumns"
      :request="requestAssetList"
      :search="{ showNumber: 2 }"
      :action-items="actionItems"
    >
      <template #table-title>
        <div class="pro-page-title-actions">
          <el-button type="primary" @click="dialogVisible = true">新增</el-button>
          <el-button type="danger">批量删除</el-button>
        </div>
      </template>
      <template #table-toolbar>
        <div class="pro-page-title-actions">
          <el-button plain>查看日志</el-button>
          <el-button plain>导出数据</el-button>
        </div>
      </template>
    </dh-pro-page>

    <el-dialog v-model="dialogVisible" title="新增记录" width="520">
      <el-form label-width="80px">
        <el-form-item label="名称">
          <el-input v-model="form.name" />
        </el-form-item>
        <el-form-item label="状态">
          <el-select v-model="form.status">
            <el-option label="未解决" value="0" />
            <el-option label="已解决" value="1" />
          </el-select>
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="dialogVisible = false">取消</el-button>
        <el-button type="primary" @click="dialogVisible = false">确定</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script lang="ts" setup>
import { reactive, ref } from 'vue'
import { actionItems, pageColumns, requestAssetList } from './shared'

const dialogVisible = ref(false)
const form = reactive({
  name: '',
  status: '0',
})
</script>

<style scoped>
.pro-page-demo {
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.pro-page-title-actions {
  display: flex;
  gap: 12px;
}
</style>

ProPage API

Props

属性名说明类型默认值
columns表格与搜索共享 schemaPcProColumn[][]
search-model / v-model:search-model搜索表单值Record{}
data表格数据(基础模式)Array[]
loading加载状态(基础模式)booleanfalse
total总条数(基础模式)number0
page / v-model:page当前页码numberdefaultPageInfo.page
page-size / v-model:page-size每页条数numberdefaultPageInfo.pageSize
requestrequest 模式的数据加载函数Function
searchSearch 透传配置;传 false 可隐藏搜索区object / false{}
tableTable 透传配置,默认带业务列表表格规范object{}
paramsrequest 模式附加参数object{}
post-data对 request 结果中的 data 做二次处理Function
before-search-submit请求前转换搜索参数Function
default-page-info默认分页参数object
default-page-size-list默认分页选项列表Array[10,20,50,100]
pagination分页配置;传 false 可关闭分页object / false
page-info-map自定义 request 中的分页字段名object
search-slot是否将 plus-field-* / plus-label-* 等插槽映射到搜索区booleanfalse
sticky-pagination分页是否固定在表格可视区底部booleantrue
search-layoutdh-pro-search 的布局stringauto
search-coldh-pro-search 的列数number自动推导
search-label-width搜索区 label 宽度string / number100px
action-items业务操作列配置PcProActionItem[][]
show-more-filter是否展示“更多筛选”入口booleanfalse

其中 search 属性会继续透传给 dh-pro-search,所以像 advancedPaneladvancedTitleadvancedDescription 这类内建高级筛选面板能力,也可以直接在 ProPage 场景里使用。

Events

事件名说明回调参数
update:search-model搜索表单值变化(v: Record)
update:page页码变化(n: number)
update:page-size每页条数变化(n: number)
search点击查询(v: Record)
reset点击重置(v: Record)
open-advanced点击“更多筛选”
request-errorrequest 失败(error)
request-completerequest 完成(result)
pagination-change页码或 pageSize 变化({ page, pageSize })

Slots

插槽名说明
search-footer自定义搜索按钮区
search-toolbar搜索区 footer 左侧业务操作区
advanced / advanced-nav / advanced-footer透传到搜索区内建高级筛选面板
table-title表格标题左侧区域
table-toolbar表格工具栏左侧区域
table-expand展开行
table-append表格底部附加区域
table-empty空状态
pagination-left / pagination-right分页器左右区域
plus-cell-* / plus-header-*自定义表格单元格 / 表头
plus-field-* / plus-label-* / plus-extra-* / plus-previous-*开启 search-slot 后映射到搜索区

Expose

方法名说明类型
getList手动触发 request 重新拉数Function
handleReset调用底层搜索区 resetFunction
setSearchFieldsValue批量设置搜索值Function
getSearchFieldsValue获取全部或单个搜索值Function
clearSearchFieldsValue清空搜索值Function
setTableData手动覆盖当前表格数据Function