Skip to content

介绍与安装 ​

介绍 ​

Admin Pro Table 是基于 Vue 3 和 Element Plus 的表格与表单组件库,组件统一以 Pro 为前缀,提供:

  • ProTable:集成搜索表单、表格、分页与增删改的列表页方案,通过配置即可完成常见 CRUD 页面。
  • ProFormPopup:配置化表单弹层,支持弹窗 / 抽屉 / 整页三种模式,可与 ProTable 配合使用,也可单独使用。
  • ProFormContent:仅表单主体(无弹层、无底部按钮),用于自有容器场景。
  • ProFormItem:单表单项,用于自定义布局或与 ProFormContent 组合。
  • ProSearchForm:搜索区表单,可独立于 ProTable 使用。

适用于后台管理、数据管理等需要列表 + 搜索 + 新增/编辑表单的场景。

依赖 ​

需已安装 Vue 3、Element Plus、@element-plus/icons-vue(版本要求见包 peerDependencies)。

安装 ​

bash
# pnpm
pnpm install admin-pro-table

# npm
npm install admin-pro-table

# yarn
yarn add admin-pro-table

使用 ​

在入口文件中注册组件并引入样式(推荐使用默认安装,会注册全部 Pro 组件):

javascript
import { createApp } from 'vue'
import AdminProTable from 'admin-pro-table'
import 'admin-pro-table/dist/style.css'
import App from './App.vue'

const app = createApp(App)
app.use(AdminProTable)

按需引入时:

javascript
import { ProTable, ProFormPopup, ProSearchForm, ProForm } from 'admin-pro-table'
import 'admin-pro-table/dist/style.css'

app.component('ProTable', ProTable)
app.component('ProFormPopup', ProFormPopup)
app.component('ProSearchForm', ProSearchForm)
app.component('ProForm', ProForm)

在页面中通过 search-config、table-config、form-config 传入配置即可使用:

vue
<template>
  <pro-table
    :search-config="searchConfig"
    :table-config="tableConfig"
    :form-config="formConfig"
  />
</template>

<script setup>
// 定义 searchConfig、tableConfig、formConfig...
</script>

组件 API 与配置项详见 ProTable、表单组件。

AI 智能助手支持 ​

本组件库内置 AI 使用指南(CLAUDE.md),安装后 AI 助手(如 Claude Code、Cursor 等)会自动读取并理解组件的完整配置结构,无需阅读文档即可准确帮你写配置。

对开发者的好处 ​

  • AI 能直接写出正确的 tableConfig / formConfig / searchConfig
  • 遇到问题时 AI 能给出精准的配置建议
  • 组件升级后 AI 立即理解新 API,无需手动更新文档

工作原理 ​

CLAUDE.md 是随包发布的机器可读文档,AI 工具在处理项目时会自动识别并加载,使 AI 能够准确理解组件的配置接口和行为逻辑。

示例 ​

安装后,你可以直接告诉 AI:

「帮我写一个用户管理列表页,包含按姓名和状态搜索,有新增、编辑、删除功能,状态用 tag 显示」

AI 会根据 CLAUDE.md 中的配置规范,直接生成完整的 searchConfig、tableConfig、formConfig 配置代码。

全局配置 ​

安装时可通过 app.use(AdminProTable, options) 的第二个参数传入全局配置。全局配置适合放项目级默认值,例如 列表请求 requestConfig、接口响应格式、分页字段名、表格默认样式、搜索表单布局、弹窗表单布局、上传配置、权限校验等。

javascript
import { createApp } from 'vue'
import AdminProTable from 'admin-pro-table'
import 'admin-pro-table/dist/style.css'
import App from './App.vue'
import { uploadFile } from '@/api/common'
import { useUserStore } from '@/stores/user'

const app = createApp(App)

app.use(AdminProTable, {
  // 列表接口响应格式:统一把任意接口结果转换成 { list, total }
  // 推荐放在 requestConfig 中;旧版顶层 responseFormat 仍兼容
  requestConfig: {
    responseFormat: (res) => ({
      list: res.data?.records ?? res.data?.list ?? [],
      total: res.data?.total ?? 0
    }),
    paramsFormat: (params) => ({ ...params, source: 'admin' }),
    pageParams: true,
    filterEmptyParams: true,
    pageKey: 'current',
    pageSizeKey: 'size',
    defaultPageSize: 20
  },
  pageSizes: [10, 20, 50, 100],

  // 接口成功判断:表单新增/编辑/保存成功后会读取 message 并提示
  successCode: 0,
  codeKey: 'code',
  messageKey: 'message',

  // 表格默认属性,单个表格可用 tableConfig.tableProps 覆盖
  tableProps: {
    border: true,
    stripe: true,
    size: 'default'
  },

  // 分页底栏默认配置,单个表格可用 tableConfig.footerConfig 覆盖
  footerConfig: {
    show: true,
    showPagination: true,
    showRefresh: true,
    pageSizes: [10, 20, 50, 100, 200],
    paginationLayout: 'total, sizes, prev, pager, next, jumper'
  },

  // 工具栏默认配置,单个表格可用 tableConfig.toolbarConfig 覆盖
  toolbarConfig: {
    showTools: true,           // 右侧三件套总开关
    showRefreshTool: true,
    showSearchToggle: true,    // 无 searchConfig 的页面仍不会显示
    showColumnSetting: true
    // columnSettingKey 建议按页面单独配,不要全局共用
  },

  // 操作列默认配置,单个表格可用 tableConfig.operationConfig 覆盖
  // 只想改操作列按钮尺寸时用 operationConfig.size,不要用全局 buttonSize(会改所有内置按钮)
  operationConfig: {
    size: 'small',
    width: 140
  },

  // 表格区域外边框默认,页面 tableConfig.bordered 优先(同搜索区 searchConfig.bordered)
  tableConfig: {
    bordered: false
  },

  // 搜索表单默认配置,单个页面 searchConfig 优先级更高
  searchConfig: {
    labelWidth: '80px',
    span: 8,
    gutter: 16,
    collapse: true,
    collapsedRows: 1,
    enterSearch: true,
    actionsConfig: {
      show: true,
      showSearch: true,
      showReset: true,
      searchText: '查询',
      resetText: '重置'
    }
  },

  // 新增/编辑弹层表单默认配置,单个页面 formConfig 优先级更高
  formConfig: {
    mode: 'dialog',
    width: '640px',
    labelWidth: '100px',
    labelPosition: 'right',
    span: 24,
    formAttrs: {
      statusIcon: true,
      scrollToError: true
    },
    footer: {
      show: true,
      showCancel: true,
      showSubmit: true,
      submitText: '确定',
      cancelText: '取消',
      align: 'right'
    }
  },

  // 上传默认配置:ProForm / ProFormPopup / ProSearchForm 内的 upload 字段都会继承
  uploadConfig: {
    api: uploadFile,
    limit: 5,
    maxSize: 10,
    accept: 'image/*',
    valueFormat: 'array',
    triggerText: '上传文件'
  },

  // 权限校验:用于工具栏按钮和操作列按钮
  hasPermission: (code) => {
    const userStore = useUserStore()
    const codes = Array.isArray(code) ? code : [code]
    return codes.some((item) => userStore.permissions.includes(item))
  },

  // 全局组件尺寸(详见 /pro-table/size);主题色由项目 Element Plus 配置统一控制
  size: 'default',
  buttonSize: 'default',

  // 空数据默认文案
  emptyText: '暂无数据'
})

app.mount('#app')

配置项说明 ​

属性说明类型默认值
requestConfig列表请求全局默认配置,支持 params、paramsFormat、beforeRequest、afterRequest、responseFormat、pageParams、pageKey、pageSizeKey、defaultPageSize、filterEmptyParams、autoFetch、requestCompleted 等,单表 tableConfig.requestConfig 可覆盖;params 对象会与全局浅合并Object-
responseFormat列表接口返回数据格式化,接收接口原始响应,返回 { list, total };推荐放入 requestConfig.responseFormat,顶层写法仍兼容Function内置解析 { data: { list, total } }、{ list, total }、{ data: [] }、{ list: [] } 或直接返回数组
filterEmptyParams列表请求是否默认过滤空搜索条件;推荐放入 requestConfig.filterEmptyParams,顶层写法仍兼容Booleantrue
pageParams列表请求是否默认自动携带分页参数;推荐放入 requestConfig.pageParams,顶层写法仍兼容Booleantrue
defaultPageSize列表首次请求默认每页条数;推荐放入 requestConfig.defaultPageSize,顶层写法仍兼容Number20
pageKey分页「当前页」请求参数名;推荐放入 requestConfig.pageKey,顶层写法仍兼容String'page'
pageSizeKey分页「每页条数」请求参数名;推荐放入 requestConfig.pageSizeKey,顶层写法仍兼容String'pageSize'
pageSizes分页器每页条数候选值Array[10, 20, 50, 100]
footerConfig表格底栏默认配置,支持 show、showPagination、showRefresh、pageSizes、paginationLayoutObject-
toolbarConfig工具栏全局默认配置,支持 showTools、showRefreshTool、showSearchToggle、showColumnSetting、columnSettingKey 等;页面 tableConfig.toolbarConfig 优先。详见 toolbarConfigObject-
operationConfig操作列全局默认配置,支持 size、width、showEdit、showDelete、showCopy 等;页面 tableConfig.operationConfig 优先。仅改操作列按钮尺寸用 { size: 'small' },详见 尺寸Object-
tableConfig表格壳层全局默认,目前支持 bordered(表格区域外边框);页面 tableConfig.bordered 优先Object-
tableProps表格全局默认属性,支持 Element Plus el-table 的所有属性,如 border、stripe、size、heightObject-
size全局组件尺寸:large / default / small,自动合并到 tableProps 与 formAttrs,详见 尺寸String-
buttonSize内置按钮尺寸(搜索、工具栏、操作列、表单底栏等),默认同 sizeString-
searchConfig搜索表单全局默认配置,如 labelWidth、span、adaptive、bordered、gutter、collapse、actionsConfig、uploadConfigObject-
formConfig表单弹层 / 独立表单全局默认配置,如 mode、width、labelWidth、span、formAttrs、footer、uploadConfigObject-
uploadConfig上传字段全局默认配置,可被 formConfig.uploadConfig、searchConfig.uploadConfig、字段级 field.uploadConfig 覆盖Object-
hasPermission权限校验函数,工具栏和操作列配置权限码时会调用Function-
emptyText表格空数据提示,也用于列空值默认展示String'暂无数据,请稍后重试~'
successCode表单接口成功状态码,String(res[codeKey]) === String(successCode) 时提示成功消息Number | String1
codeKey接口状态码字段名String'code'
messageKey接口消息字段名,成功提示优先读取该字段String'msg'

覆盖优先级 ​

全局配置只作为默认值,页面上的局部配置优先级更高:

text
字段级配置 > 当前页面配置 > 全局配置 > 组件内置默认值

常见覆盖关系:

javascript
app.use(AdminProTable, {
  tableProps: { border: true, stripe: true, size: 'default' },
  searchConfig: { labelWidth: '80px', span: 8, gutter: 16 },
  formConfig: { labelWidth: '100px', span: 24 },
  uploadConfig: { limit: 5, maxSize: 10 }
})
javascript
const tableConfig = {
  // 覆盖全局 tableProps.size,其余 border / stripe 仍继承全局配置
  tableProps: { size: 'small' }
}

const searchConfig = {
  // 覆盖全局 span,其余 labelWidth / gutter 仍继承全局配置
  span: 12,
  fields: [
    { label: '姓名', key: 'name', component: 'input' }
  ]
}

const formConfig = {
  // 覆盖全局 width / labelWidth,其余 span / footer 等仍继承全局配置
  width: '800px',
  labelWidth: '120px',
  fields: [
    {
      label: '头像',
      key: 'avatar',
      component: 'upload',
      // 字段级上传配置优先级最高
      uploadConfig: { limit: 1, accept: 'image/*', valueFormat: 'url' }
    }
  ]
}

全局 requestConfig ​

列表请求的通用配置(响应解析、分页字段、参数格式化等)建议统一放在全局 requestConfig 中,单表只需配置 api 和业务差异:

javascript
app.use(AdminProTable, {
  requestConfig: {
    responseFormat: (res) => ({
      list: res.data?.records ?? res.data?.list ?? [],
      total: res.data?.total ?? 0
    }),
    paramsFormat: (params) => ({ ...params, source: 'admin' }),
    pageKey: 'current',
    pageSizeKey: 'size',
    defaultPageSize: 20,
    pageParams: true,
    filterEmptyParams: true
  }
})
javascript
const tableConfig = {
  requestConfig: {
    api: getUserList,
    params: { type: 'user' } // 与全局 params 浅合并
  }
}

合并优先级:

text
局部 tableConfig.requestConfig > 全局 requestConfig > 旧版顶层字段 > 组件内置默认值

旧版顶层 pageKey、responseFormat、filterEmptyParams 等写法仍兼容,但新项目建议统一使用 requestConfig。详见 全局 requestConfig。

接口响应格式配置 ​

ProTable 的列表请求需要得到 { list, total }。如果你的接口不是默认结构,可以在全局 requestConfig.responseFormat 中统一转换。

例如后端返回:

javascript
{
  code: 0,
  message: 'success',
  data: {
    records: [
      { id: 1, name: 'Tom' }
    ],
    total: 32
  }
}

可全局配置:

javascript
app.use(AdminProTable, {
  requestConfig: {
    responseFormat: (res) => ({
      list: res.data?.records ?? [],
      total: res.data?.total ?? 0
    })
  },
  successCode: 0,
  codeKey: 'code',
  messageKey: 'message'
})

如果接口响应需要先做预处理,再解析列表数据,可以配合 afterRequest 和 responseFormat:

javascript
const tableConfig = {
  requestConfig: {
    api: getOrderList,
    afterRequest: (res) => res.result,
    responseFormat: (res) => ({
      list: res.items ?? [],
      total: res.count ?? 0
    })
  }
}

afterRequest 用于预处理接口原始响应,responseFormat 用于把响应转换成表格需要的 { list, total }。执行顺序是:api → afterRequest → responseFormat。

单个表格接口结构特殊时,也可以只在当前表格覆盖:

javascript
const tableConfig = {
  requestConfig: {
    api: getOrderList,
    responseFormat: (res) => ({
      list: res.result?.items ?? [],
      total: res.result?.count ?? 0
    })
  },
  columns: [
    { label: '订单号', key: 'orderNo' },
    { label: '金额', key: 'amount' }
  ]
}

分页参数配置 ​

默认请求参数为:

javascript
{
  page: 1,
  pageSize: 20,
  ...searchParams
}

如果后端需要 current / size,在全局 requestConfig 中配置:

javascript
app.use(AdminProTable, {
  requestConfig: {
    pageKey: 'current',
    pageSizeKey: 'size',
    defaultPageSize: 20
  }
})

某个接口单独使用其他字段名时,可在 requestConfig 中覆盖:

javascript
const tableConfig = {
  requestConfig: {
    api: getList,
    pageKey: 'pageNo',
    pageSizeKey: 'limit',
    defaultPageSize: 50
  }
}

如果接口没有分页,不希望自动携带分页字段,可以关闭分页参数。关闭后会同时自动隐藏分页器:

javascript
// 全局关闭:所有 ProTable 默认都不传分页字段
app.use(AdminProTable, {
  requestConfig: { pageParams: false }
})

// 单个表格关闭:仅当前列表不传分页字段
const tableConfig = {
  requestConfig: {
    api: getDictList,
    pageParams: false
  }
}

局部配置优先于全局配置,因此全局关闭后,某个分页接口仍可单独开启:

javascript
const tableConfig = {
  requestConfig: {
    api: getPagedList,
    pageParams: true
  }
}

pageParams 和 footerConfig.showPagination 的职责不同:pageParams: false 表示接口不分页,会不传分页参数并强制隐藏分页器;footerConfig.showPagination: false 只控制分页器显示,不影响请求是否携带分页参数。

请求参数格式化 ​

搜索条件默认会过滤空字符串、null、undefined 和空数组。如果接口需要接收空值,可在全局 requestConfig 中关闭:

javascript
app.use(AdminProTable, {
  requestConfig: { filterEmptyParams: false }
})

也可以只对单个表格关闭:

javascript
const tableConfig = {
  requestConfig: {
    api: getUserList,
    filterEmptyParams: false
  }
}

paramsFormat 可在全局或单表配置,用于统一转换最终请求参数。它会在固定参数、分页参数、搜索条件合并后执行,并早于 beforeRequest:

javascript
// 全局:所有表格请求统一补充字段
app.use(AdminProTable, {
  requestConfig: {
    paramsFormat: (params) => ({ ...params, source: 'admin' })
  }
})

// 单表:覆盖或追加转换逻辑
const tableConfig = {
  requestConfig: {
    api: getUserList,
    paramsFormat: (params) => ({
      ...params,
      status: params.status === '' ? undefined : Number(params.status)
    })
  }
}

paramsFormat 适合做字段改名、类型转换、补充固定字段;如果需要按条件取消请求,使用 beforeRequest 并返回 false。

全局搜索表单默认值 ​

适合统一搜索区布局、按钮文案、折叠行为:

javascript
app.use(AdminProTable, {
  searchConfig: {
    labelWidth: '84px',
    span: 8,
    gutter: 16,
    collapse: true,
    collapsedRows: 1,
    defaultCollapsed: false,
    enterSearch: true,
    actionsConfig: {
      show: true,
      showSearch: true,
      showReset: true,
      searchText: '搜索',
      resetText: '清空'
    }
  }
})

页面中只需要写差异部分:

javascript
const searchConfig = {
  model: { name: '', status: '' },
  fields: [
    { label: '姓名', key: 'name', component: 'input' },
    {
      label: '状态',
      key: 'status',
      component: 'select',
      options: [
        { label: '启用', value: 1 },
        { label: '禁用', value: 0 }
      ]
    }
  ]
}

全局表单默认值 ​

适合统一弹窗宽度、表单 label、底部按钮和 Element Plus Form 属性:

javascript
app.use(AdminProTable, {
  formConfig: {
    mode: 'dialog',
    width: '720px',
    labelWidth: '110px',
    labelPosition: 'right',
    span: 24,
    formAttrs: {
      statusIcon: true,
      scrollToError: true,
      validateOnRuleChange: false
    },
    footer: {
      show: true,
      showCancel: true,
      showSubmit: true,
      showSave: false,
      cancelText: '取消',
      submitText: '提交',
      saveBtnTitle: '保存草稿',
      align: 'right'
    }
  }
})

页面表单可以覆盖局部配置:

javascript
const formConfig = {
  width: '900px',
  labelWidth: '130px',
  span: 12,
  model: { name: '', phone: '', remark: '' },
  fields: [
    { label: '姓名', key: 'name', component: 'input' },
    { label: '手机号', key: 'phone', component: 'input' },
    { label: '备注', key: 'remark', component: 'textarea', rows: 3, span: 24 }
  ],
  add: { title: '新增用户', api: createUser },
  edit: { title: '编辑用户', api: updateUser }
}

全局上传配置 ​

uploadConfig 可以配置在三个层级:

text
字段级 field.uploadConfig > 当前表单/搜索 uploadConfig > 全局 uploadConfig

全局配置示例:

javascript
app.use(AdminProTable, {
  uploadConfig: {
    api: async (file, formData) => {
      const data = new FormData()
      data.append('file', file)
      data.append('bizType', formData.type || 'default')
      const res = await uploadFile(data)
      return {
        url: res.data.url,
        name: res.data.name || file.name
      }
    },
    limit: 5,
    maxSize: 10,
    accept: 'image/*',
    valueFormat: 'array',
    triggerText: '点击上传',
    showName: true
  }
})

字段覆盖示例:

javascript
fields: [
  {
    label: '头像',
    key: 'avatar',
    component: 'upload',
    uploadConfig: {
      limit: 1,
      accept: 'image/*',
      valueFormat: 'url',
      triggerText: '上传头像'
    }
  },
  {
    label: '附件',
    key: 'files',
    component: 'upload',
    uploadConfig: {
      limit: 10,
      accept: '.pdf,.doc,.docx,.xlsx',
      valueFormat: 'array'
    }
  }
]

权限校验配置 ​

配置 hasPermission 后,工具栏按钮和操作列按钮可以通过权限码控制显示。

javascript
app.use(AdminProTable, {
  hasPermission: (code) => {
    const permissions = JSON.parse(localStorage.getItem('permissions') || '[]')
    const codes = Array.isArray(code) ? code : [code]
    return codes.some((item) => permissions.includes(item))
  }
})

页面中配置权限码:

javascript
const tableConfig = {
  toolbarConfig: {
    showAdd: true,
    showDelete: true,
    addPermission: 'user:add',
    deletePermission: 'user:delete'
  },
  operationConfig: {
    showEdit: true,
    showDelete: true,
    showCopy: true,
    editPermission: 'user:edit',
    deletePermission: (row) => row.systemBuiltIn ? '' : 'user:delete',
    copyPermission: ['user:add', 'user:copy']
  }
}

未配置权限码,或未配置全局 hasPermission 时,按钮默认显示。

完整页面示例 ​

下面示例展示全局配置后,页面只保留业务差异配置:

vue
<template>
  <ProTable
    :search-config="searchConfig"
    :table-config="tableConfig"
    :form-config="formConfig"
  >
    <template #status="{ row }">
      <el-tag :type="row.status === 1 ? 'success' : 'danger'">
        {{ row.status === 1 ? '启用' : '禁用' }}
      </el-tag>
    </template>
  </ProTable>
</template>

<script setup>
import { reactive } from 'vue'
import { getUserList, createUser, updateUser, deleteUser } from '@/api/user'

const searchConfig = reactive({
  model: { name: '', status: '' },
  fields: [
    { label: '姓名', key: 'name', component: 'input' },
    {
      label: '状态',
      key: 'status',
      component: 'select',
      options: [
        { label: '启用', value: 1 },
        { label: '禁用', value: 0 }
      ]
    }
  ]
})

const tableConfig = reactive({
  requestConfig: {
    api: getUserList,
    params: { source: 'admin' }
  },
  columns: [
    { label: '姓名', key: 'name', minWidth: 120 },
    { label: '状态', key: 'status', slot: 'status', width: 100 },
    { label: '创建时间', key: 'createTime', width: 180 }
  ],
  rowKey: 'id',
  toolbarConfig: {
    showAdd: true,
    showDelete: true,
    addPermission: 'user:add',
    deletePermission: 'user:delete'
  },
  operationConfig: {
    showEdit: true,
    showDelete: true,
    editPermission: 'user:edit',
    deletePermission: 'user:delete'
  },
  deleteConfig: {
    api: deleteUser,
    idField: 'id',
    paramKey: 'id'
  }
})

const formConfig = reactive({
  model: { name: '', phone: '', status: 1, avatar: '', remark: '' },
  fields: [
    { label: '姓名', key: 'name', component: 'input', rules: [{ required: true, message: '请输入姓名' }] },
    { label: '手机号', key: 'phone', component: 'input' },
    {
      label: '状态',
      key: 'status',
      component: 'select',
      options: [
        { label: '启用', value: 1 },
        { label: '禁用', value: 0 }
      ]
    },
    {
      label: '头像',
      key: 'avatar',
      component: 'upload',
      uploadConfig: { limit: 1, valueFormat: 'url' }
    },
    { label: '备注', key: 'remark', component: 'textarea', rows: 3, span: 24 }
  ],
  add: { title: '新增用户', api: createUser },
  edit: { title: '编辑用户', api: updateUser }
})
</script>

更多配置细节可继续查看 配置总览、搜索组件、表单弹层配置 和 上传配置。