@bireturn/ag-grid
v1.0.1
Published
基于 AG Grid v28 封装的 Vue 3 企业级表格组件库,内置服务端分页、字典渲染、行内编辑、表单搜索等能力。
Downloads
123
Readme
@bireturn/ag-grid
基于 AG Grid v28 封装的 Vue 3 企业级表格组件库,内置服务端分页、字典渲染、行内编辑、表单搜索等能力。
安装
npm install @bireturn/ag-grid快速开始
1. 注册插件
在 main.ts 中注册,传入宿主项目的依赖:
import { createApp } from 'vue'
import { AgGridPlugin } from '@bireturn/ag-grid'
import '@bireturn/ag-grid/lib/style.css'
import { useUserStore } from '~/store/user'
import { useDefaultStore } from '~/store/store'
import { getDictByMeth, dictListToMap } from '~/api/public/public-d'
import { isAuthShow } from '~/api/public/public-auth'
import { errorMsg } from '~/utils/message'
import { excelUpLoad } from '~/api/public/downLoad'
import { serverNames } from '~/api/public/public-proxy'
import { post } from '~/service/index'
import { dataGridListByPage } from "~/api/common/admin";
const app = createApp(App)
app.use(AgGridPlugin, {
useUserStore, // () => { dictionariesTable, roleType, ... }
useDefaultStore, // () => { lang }
getDictByMeth, // (dictType, dictParams) => Promise<{value,label}[]>
dictListToMap, // (list) => Record<string, string>
isAuthShow, // (authCode) => boolean
errorMsg, // (msg: string) => void
excelUpLoad, // (serviceId, params) => Promise<void>
serverNames, // string[]
httpPost: post, // (url, data) => Promise<{success, result}>(select-table 使用)
dataGridListByPage, // (data: any) => Promise<any>
})注册后全局可用两个组件:
| 全局标签 | 说明 | 兼容原组件 |
|---|---|---|
| <bire-grid> | 纯表格(服务端数据源) | <ag-Gird> |
| <bire-form-grid> | 搜索表单 + 表格一体化 | <publicFormAgGrid> |
2. 局部使用组件(可选)
如果不希望全局注册,也可以在单个 .vue 文件中按需导入:
import { AgGridComponent, FormAgGridComponent } from '@bireturn/ag-grid'| 导出名 | 对应全局标签 | 说明 |
|---|---|---|
| AgGridComponent | <bire-grid> | 纯表格组件 |
| FormAgGridComponent | <bire-form-grid> | 搜索表单 + 表格一体化组件 |
注意:局部使用时仍需先调用
app.use(AgGridPlugin, options)完成依赖注入,组件内部通过getContext()读取注入的依赖。
<template>
<AgGridComponent
:columnDefsConfig="listAGrid.columnConfig"
:serverSideDatasource="listAGrid.dataSource"
@on-operation="listAGrid.rowBtnOnClick"
/>
</template>
<script setup lang="ts">
import { AgGridComponent, AGrid } from '@bireturn/ag-grid'
const listAGrid = new AGrid({ ... }).build()
</script>BireGrid(<bire-grid>,<ag-Gird>)
纯表格组件,搭配 AGrid 工厂类使用,数据由外部通过 serverSideDatasource 注入。
Props
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| columnDefsConfig | any[] | [] | 列定义数组,详见列类型 |
| gridOptions | object | — | AG Grid 原生 gridOptions |
| serverSideDatasource | object | — | 服务端数据源(含 getRows 方法) |
| height | string | '100%' | 容器高度 |
| pagination | boolean | true | 是否显示分页 |
| paginationPageSize | number | 30 | 默认每页条数 |
| defaultPageSize | number | 0 | 优先使用的每页条数(覆盖 paginationPageSize) |
| cardTitle | string | '' | 顶部卡片标题(空则不显示卡片) |
| showSummaries | boolean | false | 是否显示合计行 |
| isFlex | boolean | false | 列是否 flex 均分 |
| pageSizeInput | boolean | false | 是否允许手动输入每页条数 |
| excludePageSizes | number[] | [] | 分页器中排除的条数选项 |
| checkTrigerRowClick | boolean | true | 勾选 checkbox 是否同时触发行点击 |
Events
| 事件 | 参数 | 说明 |
|---|---|---|
| on-operation | (data, actionType, rowIndex, btnData) | 行按钮点击 |
| on-gridRowClick | (data) | 行点击 |
| on-gridCellDoubleClick | (event) | 单元格双击 |
| on-cellEditingStopped | (event) | 行内编辑停止 |
| on-selected | (rows) | 勾选行变化 |
| on-filterChanged | (event) | 列筛选变化 |
| on-rowEditStopped | (event) | 行编辑停止(全行编辑模式) |
Expose(ref 方法)
| 方法 | 说明 |
|---|---|
| editRow(rowIndex) | 进入行内编辑 |
| submit() | 提交当前编辑行,返回 Promise<rowData> |
| rollback(rowIndex) | 回滚指定行的编辑 |
| editAllRows() | 开启全行编辑模式 |
| cancelEditAllRows() | 退出全行编辑模式 |
| getSelectedRows() | 获取当前选中行 |
| deselectAll() | 取消所有选中 |
| getCurrentPageData() | 获取当前页所有行数据 |
基础用法
<template>
<bire-grid
:columnDefsConfig="listAGrid.columnConfig"
:gridOptions="listAGrid.gridOptions"
:serverSideDatasource="listAGrid.dataSource"
@on-operation="listAGrid.rowBtnOnClick"
@on-gridRowClick="listAGrid.gridRowClick"
:defaultPageSize="20"
>
<!-- 顶部按钮插槽 -->
<el-button type="primary" @click="handleAdd">新增</el-button>
</bire-grid>
</template>
<script setup lang="ts">
import { AGrid } from '@bireturn/ag-grid'
const listAGrid = new AGrid({
searchForm: { name: '', status: '' },
columnConfig: [
{ type: 'index' },
{ type: 'text', headerName: '名称', field: 'name', sortable: true, filter: true },
{ type: 'dictStatus', headerName: '状态', field: 'status', renderDictMap: { '1': '启用', '0': '禁用' } },
{ type: 'button', headerName: '操作', btnList: [
{ label: '编辑', actionType: 'edit', type: 'primary' },
{ label: '删除', actionType: 'delete', type: 'danger' },
]},
],
getGridDataFunc: async (params) => {
const { result } = await api.getList(params)
return result
},
rowBtnOnClick: ({ data, actionType }) => {
if (actionType === 'edit') handleEdit(data)
if (actionType === 'delete') handleDelete(data)
},
}).build()
</script>BireFormGrid(<bire-form-grid>,<publicFormAgGrid>)
搜索表单 + 表格一体化组件,通过 agGridConfig 接收全部配置。
Props
| 属性 | 类型 | 说明 |
|---|---|---|
| agGridConfig | object | 完整配置对象,详见下方字段说明 |
agGridConfig 字段
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| fetchApi | (params) => Promise<{success, result, error}> | 是 | 请求函数,result 需含 {records, total} |
| formJson | FormItem[] | — | 搜索表单项定义数组 |
| defaultParams | object | — | 默认搜索参数(初始值) |
| defaultSortParams | any[] | — | 默认排序配置 |
| rowBtnGroup | BtnItem[] | — | 行操作按钮 |
| otherBtnGroup | BtnItem[] | — | 表格顶部按钮 |
| rowBtnGroupClick | ({data, actionType, rowIndex}) => void | — | 行按钮点击回调 |
| otherBtnGroupClick | ({actionType, data}) => void | — | 顶部按钮点击回调 |
| rowClick | (data) => void | — | 行点击回调 |
| height | number | — | 表格高度(px) |
| pagination | boolean | — | 是否分页,默认 true |
| paginationPageSize | number | — | 每页条数 |
| defaultPageSize | number | — | 默认每页条数 |
| cardTitle | string | — | 顶部标题 |
| labelWidth | string | — | 表单 label 宽度,如 '100px' |
| isFlex | boolean | — | 列均分 |
| firstOnInit | boolean | — | 是否初始化时加载数据,默认 true |
| resetToDefaultParams | boolean | — | 重置时是否还原为 defaultParams,默认 false |
| exportConfig | ExportConfig | — | 导出配置 |
| serviceCode | string | — | 动态列服务码(配合 dataGridListByPage) |
| gridCode | string | — | 动态列表格码 |
| otherBtnPosition | string | — | 顶部按钮位置:'left'/'right'/'gridRight'/'onlyTable'/'table'(默认) |
| filterCol | {field} | {field}[] | — | 过滤掉的动态列字段 |
| otherRowConfig | Record<field, colDef> | — | 按字段覆盖列配置 |
| isChildren | boolean | — | 是否子表格(加载时携带父行数据) |
运行时回写字段(组件挂载后可用)
| 字段 | 说明 |
|---|---|
| config.searchForm | 当前搜索表单数据(响应式) |
| config.recordRowData | 当前点击行数据 |
| config.selectList | 当前勾选行列表 |
| config.getAllSelected(key?) | 获取勾选行(可指定取某字段) |
| config.resetAllStore() | 重置表格数据源(重新加载) |
| config.setParamsAndReset(data?) | 更新搜索条件并刷新 |
| config.setDefaultParamsAndReset(data?) | 更新条件并设为默认后刷新 |
| config.getRequestParams() | 获取最近一次请求参数的副本 |
用法示例
<template>
<bire-form-grid :agGridConfig="agGridConfig">
<template #button>
<el-button type="primary" @click="handleExport">导出</el-button>
</template>
</bire-form-grid>
</template>
<script setup lang="ts">
import { reactive } from 'vue'
const agGridConfig = reactive({
height: 500,
labelWidth: '80px',
formJson: [
{ type: 'input', label: '名称', field: 'name' },
{ type: 'select', label: '状态', field: 'status', parentId: 'STATUS_DICT' },
],
defaultParams: { name: '', status: '' },
rowBtnGroup: [
{ label: '编辑', actionType: 'edit', type: 'primary' },
],
fetchApi: async (params) => api.getList(params),
otherBtnPosition: "table", //left right table 默认为'' 即''=table gridRight 只展示otherBtnGroup且居右 slotRight 只展示插槽内容
serviceCode: "AUTH", //代理服务编码
gridCode: "PUBLIC_TABLE", //表格编码
rowBtnGroupClick: ({ data, actionType }) => {
if (actionType === 'edit') openDialog(data)
},
rowClick: (data) => { currentRow.value = data },
})
</script>插槽
| 插槽名 | 说明 |
|---|---|
| button | 按钮区追加内容 |
| table-title | 表单上方标题区 |
| agGirdTopDescribe | 表格上方描述区 |
| before-{field} | 指定表单项前插槽,作用域含 { publicAGrid } |
| after-{field} | 指定表单项后插槽 |
| {field} | 完全自定义指定表单项,作用域含 { formItem, searchForm } |
AGrid 工厂类
AGrid 用于构造 bire-grid 所需的完整配置对象。
import { AGrid } from '@bireturn/ag-grid'
import type { AGridOpts } from '@bireturn/ag-grid'
const listAGrid: AGridOpts = new AGrid({
searchForm: {}, // 搜索表单初始值
columnConfig: [], // 列定义
getGridDataFunc, // 数据获取函数
rowBtnOnClick, // 行按钮回调
gridBtnOnClick, // 顶部按钮回调
gridRowClick, // 行点击回调
exportConfig: { // 导出配置(可选)
fileName: '导出文件',
authCode: 'export:btn',
},
showSummaries: false, // 是否显示合计行
}).build()getGridDataFunc 返回格式
async (params) => {
const { result } = await api.list(params)
return result // { records: any[], total: number }
}列类型(columnDefsConfig)
每一列是一个对象,type 决定渲染方式:
通用字段
| 字段 | 说明 |
|---|---|
| type | 列类型(见下表) |
| headerName | 列标题 |
| field | 数据字段名 |
| width | 宽度(px) |
| minWidth | 最小宽度 |
| maxWidth | 最大宽度 |
| pinned | 固定列:true/'left'/'right' |
| sortable | 是否可排序 |
| filter | 是否可筛选 |
| editable | 是否可行内编辑 |
列类型一览
| type | 说明 | 特有字段 |
|---|---|---|
| index | 序号列 | — |
| selection | 勾选列 | showDisabledCheckboxes |
| text | 普通文本 | rendorData(data) 自定义渲染函数,customTooltipTextFn(data) |
| number | 数字(只读) | — |
| number2 | 数字(可编辑) | elProps, elEmits |
| defaultText | 固定显示 value 的文本 | value |
| date | 日期(截取前10位) | editable |
| datetime | 日期时间 | — |
| money | 金额(千位分隔) | — |
| Price | 价格(追加单位) | value(单位字符串) |
| toFixed | 保留小数位 | value(小数位数,默认2) |
| thousandToFixed | 千分位+小数 | value(小数位数) |
| dictStatus | 字典状态(支持筛选) | renderDictMap: Record<value, label> |
| dictStatusArr | 多值字典(逗号分隔) | value(字典类型key) |
| dictStatusArrReturnOne | 多字典合并映射 | value(多字典key,逗号分隔) |
| status | 自定义状态映射 | obj: Record<value, label>, valueFormatter? |
| tag | 标签渲染 | tags: [{value, label, type}] |
| switch | 开关 | activeValue/inactiveValue, actionType, loading |
| hoverText | 可点击文本 | url, query, actionType, moreText, defaultText, nullText |
| img | 图片 | — |
| icon | 图标 | iconName, actionType, ondition |
| light | 指示灯 | lightStatus: [{value, color, label}], tooltipRender |
| rate | 评分 | max |
| option | 下拉选择(行内可编辑) | value(字典 parentId) |
| category | 分类选择 | values: [{label, value}] |
| button | 操作按钮列 | btnList: BtnItem[] |
| tooltip | 固定值+tooltip | value |
| file | 文件/附件 | — |
| complex | 多字段合并显示 | propsArr: string[], propsNameArr: string[], separator |
行按钮(button 列 btnList)
{
label: '编辑',
actionType: 'edit',
type: 'primary', // element-plus button type
plain: true,
authCode: 'edit:btn', // 权限码(空则始终显示)
disabled: false, // 或 (row) => boolean
loading: false,
}搜索表单项(formJson)
bire-form-grid 的 formJson 数组定义表单项:
formJson: [
{ type: 'input', label: '名称', field: 'name' },
{ type: 'select', label: '状态', field: 'status', parentId: 'STATUS_DICT' },
{ type: 'selectV2', label: '人员', field: 'userId', parentId: 'USER_DICT' },
{ type: 'daterange', label: '日期范围', field: 'dateRange' },
{ type: 'monthrange', label: '月份范围', field: 'monthRange' },
{ type: 'radio', label: '类型', field: 'type', parentId: 'TYPE_DICT' },
{ type: 'checkbox', label: '标签', field: 'tags', parentId: 'TAG_DICT' },
{ type: 'switch', label: '启用', field: 'enabled' },
{ type: 'numberRange',label: '数量范围', field: 'qty' },
{
type: 'selectTable', // 带表格的下拉选择
label: '供应商',
field: 'supplierId',
parentId: 'SUPPLIER_SELECT', // 对应 selectDict 中的配置 key
},
]内置表单组件
库内置以下表单组件作为默认实现,无需宿主注册即可使用:
| type | 组件 | 说明 |
|---|---|---|
| select | public-select | 基于字典的下拉选择 |
| selectV2 | public-select-v2 | 虚拟列表下拉 |
| selectTable | select-table | 带分页表格的下拉 |
| selectTablePlus | selectTablePlus | 增强版表格下拉(支持 v-model) |
| radio | public-radio | 字典单选 |
| checkbox | public-checkbox | 字典多选 |
| switch | public-switch | 开关 |
| daterange | public-daterange | 日期范围 |
| monthrange | public-monthrange | 月份范围 |
| numberRange | numberRange | 数值范围 |
覆盖内置组件:在注册插件时传入 formComponents 字段:
app.use(AgGridPlugin, {
// ...
formComponents: {
publicSelect: MyCustomSelect,
selectTable: MyCustomSelectTable,
},
})selectDict 配置
selectTable / selectTablePlus 需要通过 selectDict 告知请求地址和列定义。支持懒加载写法(避免 Pinia 时序问题):
app.use(AgGridPlugin, {
// ...
selectDict: () => ({
SUPPLIER_SELECT: {
url: '/proxy/common-server/supplier/list',
colName: 'supplierId', // 回填字段
columnDefs: [
{ label: '编码', prop: 'supplierCode' },
{ label: '名称', prop: 'supplierName' },
],
postBody: { type: '1' }, // 固定请求参数
disableFilterKey: false, // 是否禁用关键字筛选
},
}),
})导出
使用 AGrid 导出配置(自动)
new AGrid({
exportConfig: {
fileName: '物料清单',
authCode: 'export:btn', // 可选,控制按钮显示
// 使用当前搜索参数导出
},
requestUrl: '/proxy/common-server/material/list',
})手动调用导出
import { generalExport, doGeneralExport } from '@bireturn/ag-grid'
// 自动从 URL 解析 serviceId
await generalExport(listAGrid, '/proxy/common-server/material/list', null, '导出文件')
// 完全手动
await doGeneralExport(listAGrid, 50000, 'common-server', '/material/list', params, '导出文件')工具函数
import { getDictValueMap, rowSpan, showCellRenderer } from '@bireturn/ag-grid'
// 获取字典映射表 { value -> label }
const dictMap = await getDictValueMap('SYS_STATUS')
// 支持远程字典:'common:getComboGridDataByPage'
const remoteMap = await getDictValueMap('common:MATERIAL_TYPE', { bizType: '1' })
// 合并单元格行数计算(用于 gridOptions.getRowSpan)
rowSpan(params)
// 合并单元格时隐藏多余单元格内容(用于 gridOptions.getRowClass)
showCellRenderer()合并单元格示例
new AGrid({
gridOptions: {
getRowSpan: (params) => rowSpan(params),
context: {
autoMergCols: ['category'], // 需要合并的列 field
autoPrimaryKey: ['id'], // 合并的唯一主键
},
},
})上下文注入完整类型
interface AgGridContext {
useUserStore: () => { dictionariesTable: Record<string, any[]>; roleType?: string; [key: string]: any }
useDefaultStore: () => { lang: string; [key: string]: any }
getDictByMeth: (dictType: string, dictParams: any) => Promise<{ value: string; label: string }[]>
dictListToMap: (list: any[]) => Record<string, string>
isAuthShow: (authCodes: string | string[], type?: string) => boolean
errorMsg: (msg: string) => void
excelUpLoad: (serviceId: string, params: any) => Promise<any>
serverNames: string[]
httpPost?: (url: string, data: any) => Promise<{ success: boolean; result: any }>
selectDict?: Record<string, SelectDictItem> | (() => Record<string, SelectDictItem>)
dataGridListByPage?: (data: any) => Promise<any>
getGridHeadTitle?: (serviceCode: string, gridCode: string, field: string, title: string) => string
formComponents?: { publicSelect?: any; selectTable?: any; [key: string]: any }
uploadComponent?: any
labels?: { search?: string; reset?: string; export?: string; selectOperateData?: string }
}国际化
表格语言跟随 useDefaultStore().lang 自动切换:
zh→ 中文(默认)- 其他 → 英文
构建
npm run build # 产物输出到 lib/
npm run dev # 开发预览(demo 页面)
npm run lint # ESLint 检查