Skip to content

AiCrudPage CRUD 页面组件

AiCrudPage 是 Forge Admin 的核心组件,提供完整的 CRUD 页面解决方案。集成搜索表单、数据表格(表格/卡片双模式)、新增/编辑/详情弹窗(模态框/抽屉/平铺/多页签)、批量删除、导入导出、自定义查询等功能。通过声明式配置即可快速搭建功能完备的后台管理页面。

快速上手

vue
<template>
  <AiCrudPage
    ref="crudRef"
    api="/api/user"
    :columns="columns"
    :search-schema="searchSchema"
    :edit-schema="editSchema"
    @load-list-success="onLoadSuccess"
  />
</template>

<script setup>
import { ref } from 'vue'
import { AiCrudPage } from '@/components/ai-form'

const crudRef = ref(null)

const columns = [
  { prop: 'username', label: '用户名', width: 120 },
  { prop: 'nickname', label: '昵称', width: 120 },
  { prop: 'status', label: '状态', width: 80, slot: 'status' },
  { prop: 'createTime', label: '创建时间', width: 180 }
]

const searchSchema = [
  { field: 'username', label: '用户名', type: 'input' },
  { field: 'status', label: '状态', type: 'select', props: { options: [
    { label: '启用', value: 1 },
    { label: '禁用', value: 0 }
  ] } }
]

const editSchema = [
  { field: 'username', label: '用户名', type: 'input', required: true, rules: [{ required: true, message: '请输入用户名' }] },
  { field: 'nickname', label: '昵称', type: 'input' },
  { field: 'status', label: '状态', type: 'radio', defaultValue: 1, props: { options: [
    { label: '启用', value: 1 },
    { label: '禁用', value: 0 }
  ] } }
]
</script>

Props

以下为所有 Props 速览表。复杂对象类型(🔼 标记)可点击跳转到详细说明。

核心配置

属性类型默认值说明
apiString''RESTful 基础路径,组件自动拼接 CRUD 接口。示例:'/api/user'
apiConfigObject{}▶ 完整 API 配置 — 自定义每个接口地址,优先级高于 api
rowKeyString | Function'id'行数据唯一标识字段
lazyBooleanfalsetrue 时初始不加载数据,需手动调用 refresh()
loadDetailOnEditBooleanfalse编辑时是否通过详情接口加载最新数据
isEncryptBooleanfalse是否对请求参数启用加密
publicQueryObject{}公共查询参数,拼接到 URL query string
publicParamsObject{}公共请求参数,合并到 POST body
formDefaultValuesObject{}新增/编辑弹窗打开时的默认表单值
submitDefaultParamsObject{}提交时固定附加到提交数据的参数

搜索区域

属性类型默认值说明
searchSchemaArray[]▶ 搜索表单字段配置
showSearchBooleantrue是否显示搜索区域
searchGridColsNumber4搜索表单每行最多几个字段
searchLabelWidthString | Number'auto'搜索表单标签宽度,如 '80px'100
searchEnableCollapseBooleantrue字段超过阈值时自动折叠
searchMaxVisibleFieldsNumber3折叠前最大可见字段数
searchYGapNumber10搜索项行间距(px)

表格配置

属性类型默认值说明
columnsArray[]▶ 表格列配置
tableSizeString'medium'表格尺寸:'small' | 'medium' | 'large'
tablePropsObject{}透传给 Naive UI DataTable 的额外属性
tableRowGapNumber0行间距附加高度(px),用于低代码列表预览
hideSelectionBooleanfalse是否隐藏多选框列
stripedBooleanfalse是否显示斑马纹
borderedBooleanfalse是否显示表格边框
maxHeightNumber | String表格最大高度,超出纵向滚动
scrollXNumber横向滚动最小宽度(px)
resizableBooleantrue列宽是否可拖拽调整
renderModeString'table'渲染模式:'table' 表格 | 'card' 卡片
renderModeOptionsArray可切换的渲染模式选项(全量/仅指定)
cardPropsObject{}▶ 卡片模式配置

编辑表单

属性类型默认值说明
editSchemaArray[]▶ 编辑表单字段配置
editGridColsNumber1编辑表单栅格列数,大表单建议 2
editLabelWidthString | Number'auto'编辑表单标签宽度
editLabelPlacementString'left'标签位置:'left' | 'top'
editLabelAlignString'right'标签文字对齐:'left' | 'right'
editSizeString'medium'表单项尺寸:'small' | 'medium' | 'large'
editShowFeedbackBooleantrue是否显示校验反馈信息
editXGapNumber16表单项列间距(px)
editYGapNumber8表单项行间距(px)
editFormClassString | Object | Array''编辑表单自定义 class
editFormStyleString | Object | Array编辑表单自定义 style

弹窗 / 打开方式

属性类型默认值说明
modalTypeString'modal'弹窗类型:'modal' 模态框 | 'drawer' 抽屉
modalWidthString'800px'新增/编辑弹窗宽度
detailModalWidthString'min(1080px, 92vw)'详情弹窗宽度
drawerPlacementString'right'抽屉弹出位置:'left' | 'right' | 'top' | 'bottom'
hideModalFooterBooleanfalse是否隐藏弹窗底部按钮
formOpenModeString''表单打开方式。'' 兼容 modalType'modal' 弹窗;'drawer' 抽屉;'flat' 平铺页面;'tabWorkspace' 多页签
hideDefaultDetailContentBooleanfalse详情模式是否隐藏默认只读表单,仅保留详情插槽
detailPanelsArray[]▶ 详情扩展面板配置
tabWorkspaceObject{}▶ 多页签工作区配置
childrenConfigArray[]▶ 主子表配置

工具栏

属性类型默认值说明
hideToolbarBooleanfalse是否隐藏整个工具栏
hideAddBooleanfalse是否隐藏新增按钮
addButtonTextString'新增'新增按钮文本
hideBatchDeleteBooleanfalse是否隐藏批量删除按钮
showImportBooleanfalse是否显示导入按钮
showExportBooleanfalse是否显示导出按钮
exportButtonTextString'导出'导出按钮文本
enableCustomQueryBooleanfalse是否启用自定义查询
customQueryConfigKeyString''自定义查询配置键
businessObjectCodeString''低代码业务对象编码
toolbarActionsArray[]▶ 自定义工具栏按钮
runtimeActionsArray[]▶ 运行态行操作按钮

纯填报表单 (formOnly)

属性类型默认值说明
formOnlyBooleanfalse纯填报模式,不渲染列表和工具栏,仅展示填写表单
formOnlyTitleString''填报页标题
formOnlySubmitTextString'提交'提交按钮文案
formOnlySuccessTitleString'提交成功'提交成功后显示的标题
formOnlySuccessDescriptionString'单据已保存'提交成功后显示的描述

分页

属性类型默认值说明
showPaginationBooleantrue是否显示分页组件
pageNumNumber1初始页码
pageSizeNumber10每页条数
pageSizesArray[10, 20, 50, 100]每页条数可选值

导入导出

属性类型默认值说明
importApiString''导入接口地址,格式 '{method}@{path}'
importHeadersObject{}导入请求自定义 Header
importDataObject{}导入时附加的额外参数,合并到 FormData
importTemplateUrlString''导入模板下载地址
exportApiString''导出接口地址
exportFileNameString''导出文件名(不含扩展名)
showExportTasksBooleantrue是否显示异步导出任务入口
exportTaskConfigKeyString''导出任务对应的动态 CRUD 配置键

扩展模式

属性类型默认值说明
treeConfigObject{}▶ 树形表配置 — 启用树形表格
expandConfigObject{}▶ 行展开配置 — 表格行展开面板
enableTreeAddChildBooleanfalse是否显示「添加下级」按钮
listMethodString'get'列表请求方法:'get' | 'post'
listDataFieldString'records'后端返回的列表数据字段名。如返回 { data: { rows: [...] } } 则设为 'rows'
listTotalFieldString'total'后端返回的总数字段名。如返回 { data: { totalCount: 100 } } 则设为 'totalCount'

钩子函数

所有钩子均可选,支持同步返回或返回 Promise。返回 false 会中断后续操作。详见 ▶ 钩子函数完整说明

钩子签名说明
beforeLoadList(params) => params列表请求前,可追加/修改请求参数
beforeRenderList(list) => list列表数据渲染前,可做映射/转换
beforeSearch(params) => params | false搜索请求前,返回 false 中断搜索
beforeRenderReset() => void点击重置按钮后回调
beforeSubmit(formData) => data | false表单提交前,返回 false 中断提交
afterBuildSubmitData(submitData) => data | false数据合并后、发送前,返回 false 中断提交
afterSubmit({ data, response, isEdit }) => void提交成功后回调
beforeDelete(rows) => boolean删除前确认,返回 false 中断删除
beforeRenderForm(data) => data打开编辑/详情弹窗前预处理
beforeRenderDetail(data) => data详情数据渲染前处理

1. 搜索表单 (searchSchema)

searchSchema 是一个 AiForm 字段 Schema 数组,每个元素定义一个搜索字段。AiForm 支持 34 种字段类型,详细参见 AiForm 字段类型速查表

每个 schema 项支持的通用属性:

属性类型默认值说明
fieldString必填字段名,绑定表单数据的 key,最终作为搜索参数传给后端
labelString表单标签文本
typeString'input'字段类型,决定渲染什么控件。支持 34 种,详见 字段类型速查表
placeholderString自动生成占位符文本。不设置时自动生成:「请输入{label}」或「请选择{label}」
propsObject{}透传给底层 Naive UI 组件的属性。例如 select 类型的 optionsmultiple 等都放在这里
requiredBooleanfalse搜索表单通常不需要 required,但定义了会显示红色星号
rulesArray[]Naive UI 校验规则,格式 [{ required: true, message: '...' }]
disabledBoolean | Functionfalse是否禁用。支持函数 (formData) => boolean 动态判断
clearableBooleantrue是否显示清除按钮
hiddenBooleanfalse是否隐藏该字段
spanNumber1栅格占位宽度,配合 searchGridCols 控制每行显示几个字段
defaultValueAny默认值,搜索表单加载时的初始值
onChangeFunction值变化回调 ({ value, field, formData, context })
vIfFunction条件渲染,接收 (formData) 参数,返回布尔值

搜索区域专用 Props:

属性类型默认值说明
showSearchBooleantrue是否显示搜索区域
searchGridColsNumber4搜索表单栅格列数(每行最多几个字段)
searchLabelWidthString | Number'auto'搜索表单标签宽度,如 '80px'100
searchEnableCollapseBooleantrue字段超过 searchMaxVisibleFields 时是否自动折叠
searchMaxVisibleFieldsNumber3折叠前最大可见字段数,超出部分折叠
searchYGapNumber10表单项行间距(px)

搜索 Schema 示例:

js
const searchSchema = [
  { field: 'username', label: '用户名', type: 'input', props: { clearable: true } },
  { field: 'status', label: '状态', type: 'select', props: { options: statusOptions, clearable: true } },
  { field: 'createTime', label: '创建时间', type: 'daterange', props: { type: 'datetimerange', valueFormat: 'timestamp' } },
]

2. 表格列 (columns)

columns 定义了表格显示哪些列,以及每一列的渲染方式。底层基于 Naive UI DataTable。

每列支持的属性:

属性类型必填说明
propString列数据字段名,对应行数据中的 key
labelString列标题
widthNumber | String固定列宽,如 120'120px'
minWidthNumber | String最小列宽,列宽不足时不会小于此值
alignString'left'列对齐方式:'left' | 'center' | 'right'
fixedString固定列:'left' | 'right'
ellipsisBoolean | Object超出宽度省略。传对象可配置 { tooltip: true } 显示完整内容
sortableBooleanfalse是否可排序
typeString列类型。'selection' = 多选框列,'index' = 序号列
slotString自定义插槽名,渲染时匹配 #table-{slot} 插槽。设置后不使用默认的 prop 文本渲染
renderFunction自定义渲染函数 (row, index) => VNode。返回 h() 创建的 VNode
actionsArray操作列按钮配置(详见下方)
showBoolean | Functiontrue列是否可见,支持函数 (row, index) => boolean
classNameString | Function列自定义 class
childrenArray多级表头的子列配置

actions 操作列配置:

用于在列上渲染操作按钮组(编辑、删除等),无需手写 slot。

属性类型必填说明
labelString按钮文本
keyString按钮唯一标识
typeString'default'按钮类型:'primary' | 'info' | 'success' | 'warning' | 'error' | 'default'
iconString图标名称
onClickFunction点击回调 (row) => void
visibleFunction按钮可见性 (row) => boolean

表格外观 Props:

属性类型默认值说明
rowKeyString | Function'id'行数据唯一标识字段名,或函数 (row) => key
hideSelectionBooleanfalse是否隐藏多选框列
stripedBooleanfalse是否显示斑马纹
borderedBooleanfalse是否显示表格边框
tableSizeString'medium'表格尺寸:'small' | 'medium' | 'large'
tableRowGapNumber0行间距附加高度(px),用于低代码列表预览
maxHeightNumber | String表格最大高度,超出后纵向滚动
scrollXNumber横向滚动最小宽度(px)
resizableBooleantrue列宽是否可拖拽调整
tablePropsObject{}透传给 Naive UI DataTable 的额外属性(覆盖默认配置)

列配置示例:

js
const columns = [
  { type: 'selection', width: 50, fixed: 'left' },
  { prop: 'id', label: 'ID', width: 80, align: 'center' },
  { prop: 'username', label: '用户名', minWidth: 120 },
  { prop: 'status', label: '状态', width: 90, render: row => h(DictTag, { dict: statusDict, value: row.status }) },
  { prop: 'remark', label: '备注', minWidth: 140, ellipsis: { tooltip: true } },
  { prop: 'createTime', label: '创建时间', width: 180, sortable: true },
  {
    prop: 'actions', label: '操作', width: 180, fixed: 'right', align: 'center',
    actions: [
      { label: '编辑', key: 'edit', type: 'primary', onClick: row => crudRef.value?.handleEdit(row) },
      { label: '删除', key: 'delete', type: 'error', onClick: row => crudRef.value?.handleDelete(row), visible: row => row.status !== 'locked' },
    ],
  },
]

3. 编辑表单 (editSchema)

editSchemasearchSchema 使用相同的 AiForm Schema 格式(详见 字段类型速查表),但新增/编辑场景通常需要 requiredrulesvIf 等功能。

编辑表单专用 Props:

属性类型默认值说明
editSchemaArray<Object>[]编辑表单字段配置
childrenConfigArray<Object>[]主子表模板的子表配置(详见 子表配置
editGridColsNumber1编辑表单栅格列数。大表单建议设为 2
editLabelWidthString | Number'auto'编辑表单标签宽度
editLabelPlacementString'left'标签位置:'left'(左对齐)| 'top'(顶部)
editLabelAlignString'right'标签文字对齐:'left' | 'right'
editSizeString'medium'表单项尺寸:'small' | 'medium' | 'large'
editShowFeedbackBooleantrue是否显示校验反馈信息
editXGapNumber16表单项列间距(px)
editYGapNumber8表单项行间距(px)
editFormClassString | Object | Array''编辑表单自定义 class
editFormStyleString | Object | Array编辑表单自定义 style
formAssetsArray<Object>[]表单资产列表,运行态按钮可打开其他独立表单

编辑 Schema 示例:

js
const editSchema = [
  { field: 'username', label: '用户名', type: 'input', span: 1,
    rules: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
    props: { placeholder: '请输入用户名' } },
  { field: 'nickname', label: '昵称', type: 'input', span: 1,
    props: { placeholder: '请输入昵称' } },
  { field: 'gender', label: '性别', type: 'radio', span: 1,
    defaultValue: 1, props: { options: [{ label: '男', value: 1 }, { label: '女', value: 0 }] } },
  { field: 'email', label: '邮箱', type: 'input', span: 1,
    rules: [{ type: 'email', message: '请输入正确的邮箱格式', trigger: 'blur' }] },
  { type: 'divider', label: '其他信息', span: 2, props: { titlePlacement: 'left' } },
  { field: 'remark', label: '备注', type: 'textarea', span: 2,
    props: { rows: 3, maxlength: 200, showCount: true } },
]

4. 弹窗/表单打开方式

属性类型默认值说明
modalTypeString'modal'弹窗类型:'modal'(模态框)| 'drawer'(抽屉)
modalWidthString'800px'新增/编辑弹窗宽度
detailModalWidthString'min(1080px, 92vw)'详情弹窗宽度
drawerPlacementString'right'抽屉位置:'left' | 'right' | 'top' | 'bottom'
hideModalFooterBooleanfalse是否隐藏弹窗底部按钮
formOpenModeString''表单打开方式。'' 兼容 modalType'modal' 弹窗;'drawer' 抽屉;'flat' 平铺页面;'tabWorkspace' 多页签工作区
hideDefaultDetailContentBooleanfalse详情模式是否隐藏默认只读表单,仅保留详情插槽
detailPanelsArray<Object>[]详情页扩展面板配置(详见 详情扩展面板
tabWorkspaceObject{}多页签工作区配置(详见 多页签工作区

5. API 配置 (apiConfig)

AiCrudPage 支持两种 API 配置方式:简单模式(只传 api 基础路径)和完整模式(传 apiConfig 对象)。

API 相关 Props:

属性类型默认值说明
apiString''RESTful 基础路径,如 '/api/user'。组件自动拼接:GET /api/user/pagePOST /api/userPUT /api/userDELETE /api/user/:idGET /api/user/:id
apiConfigObject{}自定义 API 配置,优先级高于 api。不传时由 api 自动推导
isEncryptBooleanfalse是否对请求参数启用加密
listMethodString'get'列表请求方法:'get' | 'post'
listDataFieldString'records'后端返回的列表数据字段名。如返回 { code: 200, data: { rows: [...] } } 则设为 'rows'
listTotalFieldString'total'后端返回的总数字段名。如返回 { data: { totalCount: 100 } } 则设为 'totalCount'

apiConfig 对象详细结构:

格式为 '{method}@{path}',如 'get@/api/user/page'。支持 URL 占位符 :{fieldName}

键名格式说明
list'{method}@{path}'列表查询接口。支持 GET/POST
add'{method}@{path}'新增接口
create'{method}@{path}'新增接口(别名,与 add 二选一)
update'{method}@{path}'更新接口,通常带 :id 占位符
delete'{method}@{path}'删除接口,支持批量
detail'{method}@{path}'详情接口,编辑时调用(需 loadDetailOnEdit

URL 占位符规则:

URL 中 :keyName 会被自动替换为当前行数据中对应字段的值。占位符名称必须与 rowKey 属性值一致。

js
// rowKey 默认 'id'
apiConfig: {
  update: 'put@/api/user/:id',    // 点击编辑时 → PUT /api/user/123
  detail: 'get@/api/user/:id'     // 点击详情时 → GET /api/user/123
}

// 自定义 rowKey='userId'
apiConfig: {
  update: 'put@/api/user/:userId', // → PUT /api/user/456
}

导入导出 API Props:

属性类型默认值说明
importApiString''导入接口地址,格式 '{method}@{path}'
importHeadersObject{}导入请求自定义 Header
importDataObject{}导入时附加的额外参数,合并到 FormData
importTemplateUrlString''导入模板下载地址
exportApiString''导出接口地址
exportFileNameString''导出文件名(不含扩展名)
showExportTasksBooleantrue是否显示异步导出任务入口
exportTaskConfigKeyString''导出任务对应的动态 CRUD 配置键,不传时自动解析

6. 工具栏

属性类型默认值说明
hideToolbarBooleanfalse是否隐藏整个工具栏
hideAddBooleanfalse是否隐藏新增按钮
addButtonTextString'新增'新增按钮文本
hideBatchDeleteBooleanfalse是否隐藏批量删除按钮
showImportBooleanfalse是否显示导入按钮
showExportBooleanfalse是否显示导出按钮
exportButtonTextString'导出'导出按钮文本
enableCustomQueryBooleanfalse是否启用自定义查询
customQueryConfigKeyString''自定义查询配置键
businessObjectCodeString''低代码业务对象编码,用于详情页加载流程状态

toolbarActions — 自定义工具栏按钮:

属性类型必填说明
labelString按钮文本
keyString唯一标识,用于 custom-action 事件区分
typeString'default''primary' | 'info' | 'success' | 'warning' | 'error' | 'default'
iconString图标名称
permissionCodeString权限码,无权限时自动隐藏
visibleBoolean | Functiontrue可见性控制。函数签名为 (selectedRows) => boolean
displayConditionString显示条件表达式
positionString'toolbar''toolbar' 工具栏按钮;'row' 行操作按钮
onClickFunction点击回调。工具栏按钮传入选中的行数据;行操作按钮传入当前行

runtimeActions — 运行态行操作:

结构同 toolbarActions,但 position 固定为 'row'。由低代码业务对象按记录状态动态追加。

formOnly — 纯填报表单模式:

属性类型默认值说明
formOnlyBooleanfalse开启后不渲染列表和工具栏,仅展示填写表单
formOnlyTitleString''表单填报页标题
formOnlySubmitTextString'提交'提交按钮文案
formOnlySuccessTitleString'提交成功'提交成功后显示的标题
formOnlySuccessDescriptionString'单据已保存'提交成功后显示的描述

7. 主子表 (childrenConfig)

子表配置用于在主表编辑弹窗中嵌入多个子表(如订单 + 订单明细)。

childrenConfig 每项结构:

属性类型必填说明
keyString子表唯一标识,对应提交数据中的字段名
titleString子表显示标题
fieldsArray子表字段配置,格式同 editSchema
showInDetailBooleantrue是否在详情页展示
relationTypeString'ONE_TO_MANY' 一对多
sourceFieldString子表中关联主表的字段名
targetFieldString主表中被关联的字段名
apiObject子表独立 API 配置,格式同 apiConfig(可选,不传则跟随主表提交)
js
const childrenConfig = [
  {
    key: 'items',
    title: '订单明细',
    fields: [
      { field: 'productName', label: '商品名称', type: 'input', required: true },
      { field: 'quantity', label: '数量', type: 'number', required: true, props: { min: 1 } },
      { field: 'price', label: '单价', type: 'number', required: true, props: { precision: 2 } },
    ],
    api: {
      list: 'get@/api/order/:id/items',
      add: 'post@/api/order/:id/items',
      update: 'put@/api/order/:id/items/:itemId',
      delete: 'delete@/api/order/:id/items/:itemId',
    },
  },
]

8. 分页

属性类型默认值说明
showPaginationBooleantrue是否显示分页组件
pageNumNumber1初始页码
pageSizeNumber10每页条数
pageSizesArray<Number>[10, 20, 50, 100]每页条数可选值

9. 卡片模式 (cardProps)

renderMode="card" 后,表格以卡片网格形式展示。通过 cardProps 控制卡片布局和内容。

属性类型默认值说明
cols / gridColsString'1 s:2 m:3 l:4 xl:4 2xl:4'响应式栅格列数,支持断点语法
gapNumber10卡片间距(px)
titleKey / titleFieldString第一列卡片标题字段(column.key)
fieldLimitNumber4卡片正文显示的最大字段数
selectOnClickBooleanfalse点击卡片是否触发勾选
maxHeightNumber卡片区域最大高度,超出滚动
styleObject自定义样式对象
js
const cardProps = {
  cols: '1 s:2 m:3 l:4',
  gap: 16,
  titleKey: 'name',
  fieldLimit: 6,
  selectOnClick: true,
}

卡片内容通过插槽 #table-card="{ row }" 完全自定义渲染。设置此插槽后 titleKeyfieldLimit 不再生效。


10. 多页签工作区 (tabWorkspace)

formOpenMode="tabWorkspace" 时,新增/编辑表单在页签中打开,支持同时编辑多条记录。

属性类型默认值说明
maxTabsNumber8最大同时打开的页签数
reuseRecordTabBooleantrue相同记录 ID 是否复用已有页签(而非新开)
closeAfterSaveBooleanfalse保存后是否自动关闭页签
showDirtyMarkBooleantrue未保存变更是否显示脏标记
js
const tabWorkspace = {
  maxTabs: 8,
  reuseRecordTab: true,
  closeAfterSave: false,
  showDirtyMark: true,
}

11. 详情扩展面板 (detailPanels)

在详情弹窗中,除了默认的只读表单和子表,还可以添加扩展面板展示关联数据。

detailPanels 每项结构:

属性类型必填说明
typeString面板类型:'table'(表格)| 'descriptions'(描述列表)| 'quantity-balance'(数量余额)| 'quantity-ledger'(数量台账)| 'custom'(自定义)
keyString面板唯一标识
titleString面板标题
dataSourceObject数据加载配置
dataSource.typeString'api''api' 接口加载 | 'row' 行数据 | 'static' 静态数据 | 'none' 不加载
dataSource.apiStringAPI 配置,格式 '{method}@{path}'
dataSource.paramsMapObject请求参数映射,支持 ${row.fieldName} 占位符
tableObjecttype='table' 时有效。配置 { columns, pagination, maxHeight, size, bordered }
descriptionsObjecttype='descriptions' 时有效。配置 { columns, fields }
quantityObject数量台账面板专用。配置 { queryType, paramsMap, pageSize }
js
const detailPanels = [
  {
    type: 'table', key: 'relatedOrders', title: '关联订单',
    dataSource: {
      type: 'api', api: 'get@/api/order/listByCustomer',
      paramsMap: { customerId: '${row.id}' },
    },
    table: {
      columns: [
        { prop: 'orderNo', label: '订单号', minWidth: 140 },
        { prop: 'amount', label: '金额', width: 100 },
      ],
      pagination: { pageSize: 5 },
      maxHeight: 300,
      size: 'small',
    },
  },
  {
    type: 'descriptions', key: 'summary', title: '摘要',
    descriptions: {
      columns: 3,
      fields: [
        { field: 'createUser', label: '创建人' },
        { field: 'createTime', label: '创建时间' },
      ],
    },
  },
]

12. 行展开 (expandConfig)

表格每行可展开显示额外面板,支持表格、描述列表、表单、选项卡、数量台账等多种类型。

顶层配置:

属性类型默认值说明
enabledBooleanfalse是否启用行展开
triggerString'icon'展开触发方式:'icon'(图标)| 'cell'(单元格)| 'row'(整行)
lazyBooleantrue是否懒加载面板数据
cacheBooleantrue是否缓存已加载的面板
defaultExpandedBooleanfalse是否默认展开所有行
layout.modeString'single''single' 单面板 | 'tabs' 多 Tab 面板
layout.densityString'compact'密度:'compact' | 'default' | 'loose'
layout.paddingNumber12面板内边距

panels 每项结构与 detailPanels 相同。

js
const expandConfig = {
  enabled: true,
  trigger: 'icon',
  lazy: true,
  layout: { mode: 'tabs', density: 'compact' },
  panels: [
    {
      type: 'table', key: 'members', title: '项目成员',
      dataSource: {
        type: 'api', api: 'get@/api/project/:id/members',
        paramsMap: { projectId: '${row.id}' },
      },
      table: {
        columns: [
          { prop: 'userName', label: '姓名', width: 120 },
          { prop: 'roleName', label: '角色', width: 100 },
        ],
        maxHeight: 280,
        size: 'small',
        pagination: false,
      },
    },
  ],
}

13. 树形表 (treeConfig)

当数据为树形结构时,通过 treeConfig 启用树形表格。

属性类型默认值说明
enabledBooleanfalse是否启用树形表
keyFieldString'id'节点主键字段
childrenFieldString'children'子节点字段名(后端返回的嵌套数组字段)
loadModeString'full''full' 全量加载(后端一次返回完整树)| 'lazy' 懒加载(点击展开时调接口)

启用树形表后,可配合 enableTreeAddChild 在行操作中显示「添加下级」按钮。

属性类型默认值说明
enableTreeAddChildBooleanfalse是否显示「添加下级」按钮(左树右表场景通常不需要)
js
const treeConfig = {
  enabled: true,
  keyField: 'id',
  childrenField: 'children',
  loadMode: 'full',
}

14. 钩子函数

所有钩子均为可选,支持同步返回或返回 Promise。返回 false 会中断后续操作。

钩子签名返回值说明
beforeLoadList(params)params - 修改后的请求参数列表请求前,可追加/修改请求参数
beforeRenderList(list)list - 处理后的列表数据列表数据渲染前,做映射/转换
beforeSearch(params)params | false — 返回 false 中断搜索点击搜索按钮后,请求发出前
beforeRenderReset()void点击重置按钮后回调
beforeSubmit(formData)data | false — 返回 false 中断提交表单提交前,可追加字段或做业务校验
afterBuildSubmitData(submitData)data | false — 返回 false 中断提交主从表数据合并后、发送请求前,做最终校验
afterSubmit({ data, response, isEdit })void提交成功后回调,常用于刷新列表或跳转
beforeDelete(rows)boolean — 返回 false 中断删除删除前确认
beforeRenderForm(data)data - 处理后的表单数据打开编辑/详情弹窗前预处理数据
beforeRenderDetail(data)data - 处理后的详情数据详情数据渲染前处理

15. 其他配置

属性类型默认值说明
lazyBooleanfalse初始不加载列表数据,需手动调用 refresh()
loadDetailOnEditBooleanfalse编辑时是否通过详情接口加载最新数据(开启后多一次请求,但数据更准确)
publicQueryObject{}公共查询参数,拼接到 URL query string。不会随搜索变化
publicParamsObject{}公共请求参数,合并到请求 body(POST)
formDefaultValuesObject{}新增/编辑弹窗打开时的默认表单值
submitDefaultParamsObject{}提交时固定合并到提交数据的参数

字段类型速查表

searchSchemaeditSchema 的每个字段通过 type 属性决定渲染哪种控件。以下是全部 34 种类型的详细说明。

基础输入类

type渲染组件关键属性 (props / 顶层)
input<n-input>placeholder, maxlength, showCount, type: 'password'
textarea<n-input type="textarea">rows(默认 3), maxlength, showCount, autosize
number / inputnumber / input-number<n-input-number>min, max, step(默认 1), precision, showButton(默认 true)
switch<n-switch>checkedValue(默认 true), uncheckedValue(默认 false), checkedText, uncheckedText
slider<n-slider>min(默认 0), max(默认 100), step(默认 1), marks, tooltip
rate<n-rate>count(默认 5), allowHalf
color / colorPicker<n-color-picker>showAlpha, modes(默认 ['hex']
text只读文本formatter: (value, field, formData) => string, copy: true 显示复制按钮

选择类

type渲染组件关键属性
select<n-select>options: [{ label, value }], multiple, filterable(默认 true), remote, onSearch, dictType
dictSelect<DictSelect>dictType, multiple, filterable, cascade: { sourceField, sourceDictType, mode, emptyStrategy }
radio<n-radio-group>options: [{ label, value }], dictType
radioButton<n-radio-group> + <n-radio-button>同 radio。props: { button: true } 等效
checkbox<n-checkbox-group>options: [{ label, value }], dictType
cascader<n-cascader>options(树形), dictType, multiple, filterable, cascade, showPath
treeSelect<n-tree-select>同 cascader
transfer<n-transfer>options, filterable
orgTreeSelect / orgSelect / departmentSelect / 等<n-tree-select>自动从 /system/org/tree 加载数据,支持 multiple, filterable, cascade
userSelect / userPicker / user / 等<UserSelectPicker>用户选择器,支持 multiple
regionTreeSelect<RegionTreeSelect>行政区划树,支持 filterable
customSelect<AiCustomSelect>api: 'get@/api/xxx', labelField, valueField, remote, transform
objectReference<n-select>(远程)referenceObjectCode, referenceValueField, referenceDisplayField
recordSelector<AiRecordSelectorModal>selectorTitle, 各 *ObjectCode / *Code 属性, displayFields, keywordFields, fieldMappings

日期时间类

type渲染组件关键属性
date<n-date-picker type="date">format(默认 'yyyy-MM-dd'), valueFormat(默认同 format)
datetime<n-date-picker type="datetime">默认格式 'yyyy-MM-dd HH:mm:ss'
month<n-date-picker type="month">默认格式 'yyyy-MM'
year<n-date-picker type="year">默认格式 'yyyy'
time<n-time-picker>默认格式 'HH:mm:ss'
daterange<n-date-picker type="daterange">startPlaceholder: '开始日期', endPlaceholder: '结束日期', 值格式同上
datetimerange<n-date-picker type="datetimerange">默认占位 '开始时间' / '结束时间',格式 'yyyy-MM-dd HH:mm:ss'
timerange<n-time-picker>类似 daterange,格式 'HH:mm:ss'

上传类

type渲染组件关键属性
upload<n-upload>action, headers, data, max, accept, multiple, listType, uploadText
fileUpload<FileUpload>action, businessType, businessId, storageType, limit, fileSize, fileType, multiple, valueType
imageUpload<ImageUpload>同 fileUpload。额外 limit 控制最大图片数,tip 显示提示文本

特殊类型

type渲染组件关键属性
slot<slot>slotName(默认为 field.field 的值),插槽暴露 { value, field, formData, updateValue }
divider<AiFormSectionTitle>分组分隔线,label 显示标题文本。span: 2 可占满整行
card<n-card>卡片容器,可嵌套子字段。子字段通过 children 数组定义
tabs + tabPane<n-tabs> + <n-tab-pane>选项卡布局,每个 tabPane 内含独立子字段
collapse + collapseItem<n-collapse> + <n-collapse-item>折叠面板布局
row + col栅格行/列高级布局控制,row 内含多个 colcol 内含子字段

所有字段通用的配置属性

无论哪种 type,都支持以下属性:

js
{
  field: 'fieldName',           // 字段名(必填)
  label: '显示标签',             // 标签文本
  type: 'input',                // 字段类型(必填)
  span: 1,                      // 栅格宽度,配合 editGridCols 控制每行几个字段
  required: false,              // 是否必填(显示红色星号)
  rules: [],                    // Naive UI 校验规则
  defaultValue: '',             // 默认值
  placeholder: '',              // 占位符(不设则自动生成)
  disabled: false,              // 禁用(支持函数 (formData) => boolean)
  clearable: true,              // 是否可清空
  hidden: false,                // 是否隐藏
  vIf: (formData) => true,      // 条件渲染
  props: {},                    // 透传给底层组件的属性
  onChange: ({ value, field, formData, context }) => {},  // 值变化回调
  labelTip: '',                 // 标签旁问号提示
  description: '',              // 控件下方描述文字
  showFeedback: true,           // 是否显示校验反馈
}

事件

事件名参数触发时机
load-list-success{ list, total, params }列表数据加载成功
load-list-error{ error, params }列表数据加载失败
add{ defaultValues }点击新增,弹窗打开后
edit{ row }点击编辑,弹窗打开后
detail{ row }点击详情,弹窗打开后
delete{ row, rows }删除成功
submit-success{ data, response, isEdit }新增或编辑提交成功
submit-error{ error, isEdit }新增或编辑提交失败
selection-change{ keys, rows }表格多选状态变化
modal-open{ status: 'add' | 'edit' | 'detail', row }弹窗打开
modal-close弹窗关闭
render-mode-change{ mode: 'table' | 'card' }切换列表/卡片模式
custom-action{ action, row, rows }自定义工具栏按钮点击。actiontoolbarActions 中的 key

插槽

工具栏插槽

插槽名说明
toolbar覆盖整个工具栏区域
toolbar-start工具栏左侧(与默认按钮共存)
toolbar-end工具栏右侧(与默认按钮共存)
toolbar-right-start右侧操作区开始位置
toolbar-right-end右侧操作区结束位置

表格列插槽

列插槽名格式:table-{slot},其中 {slot}columns 中该列定义的 slot 属性值。插槽 props:{ row, index }

vue
<template #table-status="{ row }">
  <n-tag :type="row.status === 1 ? 'success' : 'default'">{{ row.status === 1 ? '启用' : '禁用' }}</n-tag>
</template>

卡片渲染插槽

table-card:卡片模式下完全自定义卡片内容。props:{ row }

搜索表单插槽

格式:search-{field},其中 {field} 为 searchSchema 中该字段的 field 值。

编辑/详情表单插槽

格式:form-{field},其中 {field} 为 editSchema 中该字段的 field 值。额外支持 form-group-header="{ group }"


暴露方法

通过 ref 获取组件实例后调用:

js
const crudRef = ref(null)

crudRef.value.refresh()                    // 刷新列表(保持搜索条件和分页)
crudRef.value.search()                     // 触发搜索(重置到第一页)
crudRef.value.loadList({ name: 'test' })  // 加载列表,可传入额外参数
crudRef.value.getSelectedRows()            // 获取选中行数据 → Array
crudRef.value.getSelectedKeys()            // 获取选中行主键 → Array
crudRef.value.setSelectedKeys([1, 2, 3])  // 通过主键数组设置选中
crudRef.value.clearSelection()             // 清除所有选中
crudRef.value.getTableData()               // 获取当前表格全部数据 → Array
crudRef.value.setTableData([...])          // 直接设置表格数据(不触发请求)

进阶用法

主子表 CRUD

vue
<AiCrudPage
  api="/api/order"
  :columns="orderColumns"
  :edit-schema="orderEditSchema"
  :children-config="orderItemConfig"
  :edit-grid-cols="2"
  modal-width="960px"
/>
js
const orderItemConfig = [{
  key: 'items', title: '订单明细',
  fields: [
    { field: 'productName', label: '商品名称', type: 'input', required: true },
    { field: 'quantity', label: '数量', type: 'number', required: true, props: { min: 1 } },
    { field: 'price', label: '单价', type: 'number', required: true, props: { precision: 2 } },
  ],
  api: {
    list: 'get@/api/order/:id/items',
    add: 'post@/api/order/:id/items',
    update: 'put@/api/order/:id/items/:itemId',
    delete: 'delete@/api/order/:id/items/:itemId',
  },
}]

左树右表

vue
<AiCrudPage
  api="/api/dept"
  :columns="deptColumns"
  :tree-config="{ enabled: true, keyField: 'id', childrenField: 'children', loadMode: 'full' }"
  :enable-tree-add-child="false"
  hide-add
/>

纯填报表单

vue
<AiCrudPage
  :edit-schema="formSchema"
  :edit-grid-cols="2"
  form-only
  form-only-title="员工入职登记"
  form-only-submit-text="提交入职申请"
  :api-config="{ add: 'post@/api/employee/onboarding' }"
  @submit-success="onSubmitSuccess"
/>

卡片模式

vue
<AiCrudPage
  api="/api/product"
  :columns="productColumns"
  :edit-schema="productEditSchema"
  render-mode="card"
  :show-render-mode-switch="true"
  :card-props="{ cols: '1 s:2 m:3 l:4', gap: 16, fieldLimit: 6 }"
>
  <template #table-card="{ row }">
    <div class="product-card">
      <img :src="row.image" />
      <h4>{{ row.name }}</h4>
      <p>¥{{ row.price }}</p>
    </div>
  </template>
</AiCrudPage>

抽屉编辑 + 行展开子表

vue
<AiCrudPage
  api="/api/project"
  :columns="projectColumns"
  :edit-schema="projectEditSchema"
  modal-type="drawer"
  drawer-placement="right"
  modal-width="720px"
  :expand-config="{
    enabled: true,
    trigger: 'icon',
    lazy: true,
    layout: { mode: 'tabs', density: 'compact' },
    panels: [{
      type: 'table', key: 'members', title: '项目成员',
      dataSource: {
        type: 'api', api: 'get@/api/project/:id/members',
        paramsMap: { projectId: '${row.id}' },
      },
      table: {
        columns: memberColumns,
        maxHeight: 280, size: 'small', pagination: false,
      },
    }],
  }"
/>

自定义工具栏 + 确认删除

vue
<AiCrudPage
  ref="crudRef"
  api="/api/order"
  :columns="orderColumns"
  :toolbar-actions="[
    { label: '批量审批', key: 'batch-audit', type: 'info', icon: 'check-circle', onClick: handleBatchAudit },
    { label: '导出选中', key: 'export-selected', type: 'warning' },
  ]"
  :before-delete="async (rows) => {
    return await dialog.warning({
      title: '确认删除',
      content: `确定删除选中的 ${rows.length} 条记录?不可恢复。`,
      positiveText: '确认删除',
    }) !== false
  }"
  :before-submit="(formData) => ({ ...formData, updatedBy: userStore.userId })"
  @custom-action="({ action, rows }) => { if (action === 'batch-audit') auditRows(rows) }"
/>

多页签录入

vue
<AiCrudPage
  api="/api/contract"
  :columns="contractColumns"
  :edit-schema="contractEditSchema"
  :children-config="contractItemsConfig"
  form-open-mode="tabWorkspace"
  :tab-workspace="{ maxTabs: 8, reuseRecordTab: true, closeAfterSave: false }"
  modal-width="1024px"
/>

注意事项

  1. columns 为必填项,至少需包含 proplabel
  2. apiapiConfig 二选一即可,apiConfig 优先级更高
  3. URL 占位符名称需与 rowKey 属性值一致
  4. 钩子函数返回 false 会中断操作且不弹提示,需自行处理用户反馈
  5. lazy=true 时初始不加载列表,需手动调用 refresh()search()
  6. 大表单建议设 editGridCols=2,配合 modalWidth 调整弹窗宽度
  7. 卡片模式需通过 #table-card 插槽或 cardProps.titleKey 自定义渲染
  8. searchSchemaeditSchema 共享同一套字段类型体系,但搜索表单通常不需要 required 校验

Forge Admin — 基于 Vue3 + Spring Boot 的企业级后台管理框架