|
|
@@ -1849,3 +1849,596 @@ async function handleSubmit() {
|
|
|
| [user.data.ts](file:///d:/Code/Project/湛江人社/code/zjrs-jeecgBoot/jeecgboot-vue3/src/views/system/user/user.data.ts) | 用户表单校验规则示例 |
|
|
|
| [IFormSchema.ts](file:///d:/Code/Project/湛江人社/code/zjrs-jeecgBoot/jeecgboot-vue3/src/views/super/online/cgform/auto/comp/factory/IFormSchema.ts) | Online 表单 Schema 基类 |
|
|
|
| [useAutoForm.ts](file:///d:/Code/Project/湛江人社/code/zjrs-jeecgBoot/jeecgboot-vue3/src/views/super/online/cgform/hooks/auto/useAutoForm.ts) | Online 表单唯一校验 |
|
|
|
+
|
|
|
+***
|
|
|
+
|
|
|
+## 十七、BasicTable 插槽(Slot)用法详解
|
|
|
+
|
|
|
+> 追加日期:2026-06-02
|
|
|
+
|
|
|
+### 17.1 插槽机制概述
|
|
|
+
|
|
|
+BasicTable 的插槽机制由以下核心文件协同实现:
|
|
|
+
|
|
|
+| 文件 | 作用 |
|
|
|
+|----------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------|
|
|
|
+| [BasicTable.vue](file:///d:/Code/Project/湛江人社/code/zjrs-jeecgBoot/jeecgboot-vue3/src/components/Table/src/BasicTable.vue) | 主组件,模板中定义插槽透传逻辑 |
|
|
|
+| [useTableHeader.ts](file:///d:/Code/Project/湛江人社/code/zjrs-jeecgBoot/jeecgboot-vue3/src/components/Table/src/hooks/useTableHeader.ts) | 处理表头区域插槽(tableTitle, toolbar, headerTop, tableTop, alertAfter) |
|
|
|
+| [useTableForm.ts](file:///d:/Code/Project/湛江人社/code/zjrs-jeecgBoot/jeecgboot-vue3/src/components/Table/src/hooks/useTableForm.ts) | 处理搜索表单插槽(form-xxx) |
|
|
|
+| [TableHeader.vue](file:///d:/Code/Project/湛江人社/code/zjrs-jeecgBoot/jeecgboot-vue3/src/components/Table/src/components/TableHeader.vue) | 表头区域布局组件,渲染 headerTop/tableTitle/toolbar/tableTop/alertAfter |
|
|
|
+
|
|
|
+**插槽分类流程
|
|
|
+**([BasicTable.vue](file:///d:/Code/Project/湛江人社/code/zjrs-jeecgBoot/jeecgboot-vue3/src/components/Table/src/BasicTable.vue)
|
|
|
+中 `slotNamesGroup` 计算属性):
|
|
|
+
|
|
|
+```
|
|
|
+用户在 <BasicTable> 中定义的插槽
|
|
|
+ |
|
|
|
+ v
|
|
|
+slotNamesGroup 计算属性自动分类
|
|
|
+ |
|
|
|
+ +----+----+
|
|
|
+ | |
|
|
|
+ v v
|
|
|
+native组 custom组 + 单独处理的插槽
|
|
|
+ | | |
|
|
|
+ v v v
|
|
|
+直接透传 列级自定义 bodyCell: 优先匹配 slotsBak.customRender
|
|
|
+给 antd 插槽渲染 form-xxx: 去掉前缀后传给 BasicForm
|
|
|
+<Table> tableTitle/toolbar/headerTop/tableTop/alertAfter:
|
|
|
+ 由 useTableHeader 传给 TableHeader 组件
|
|
|
+ expandedRowRender/summary:
|
|
|
+ 直接在 <Table> 模板中使用
|
|
|
+```
|
|
|
+
|
|
|
+### 17.2 完整插槽列表
|
|
|
+
|
|
|
+#### 第一类:表头区域插槽
|
|
|
+
|
|
|
+##### 1. `tableTitle` — 表格标题/操作按钮区域
|
|
|
+
|
|
|
+- **位置**:表格标题栏左侧
|
|
|
+- **用途**:放置新增、导出、导入、批量操作等按钮,**最常用的插槽**
|
|
|
+- **作用域参数**:无
|
|
|
+
|
|
|
+```vue
|
|
|
+
|
|
|
+<template #tableTitle>
|
|
|
+ <a-button type="primary" preIcon="ant-design:plus-outlined" @click="handleCreate">新增</a-button>
|
|
|
+ <a-button type="primary" preIcon="ant-design:export-outlined" @click="onExportXls">导出</a-button>
|
|
|
+ <j-upload-button type="primary" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
|
|
|
+ <a-dropdown v-if="selectedRowKeys.length > 0">
|
|
|
+ <template #overlay>
|
|
|
+ <a-menu>
|
|
|
+ <a-menu-item key="1" @click="batchHandleDelete">
|
|
|
+ <Icon icon="ant-design:delete-outlined"></Icon>
|
|
|
+ 删除
|
|
|
+ </a-menu-item>
|
|
|
+ </a-menu>
|
|
|
+ </template>
|
|
|
+ <a-button>批量操作
|
|
|
+ <Icon icon="mdi:chevron-down"></Icon>
|
|
|
+ </a-button>
|
|
|
+ </a-dropdown>
|
|
|
+</template>
|
|
|
+```
|
|
|
+
|
|
|
+**源码实现
|
|
|
+**:[useTableHeader.ts](file:///d:/Code/Project/湛江人社/code/zjrs-jeecgBoot/jeecgboot-vue3/src/components/Table/src/hooks/useTableHeader.ts)
|
|
|
+将 `tableTitle` 插槽通过 `h()`
|
|
|
+函数传递给 [TableHeader.vue](file:///d:/Code/Project/湛江人社/code/zjrs-jeecgBoot/jeecgboot-vue3/src/components/Table/src/components/TableHeader.vue)
|
|
|
+,TableHeader 中将其渲染在左侧 `__tableTitle` 区域。当未使用此插槽但配置了 `title` prop 时,会渲染默认的 `TableTitle` 组件。
|
|
|
+
|
|
|
+##### 2. `toolbar` — 工具栏区域
|
|
|
+
|
|
|
+- **位置**:表格标题栏右侧,与 TableSetting(列配置按钮)同行
|
|
|
+- **用途**:放置工具按钮,如"获取表单数据"、"切换自适应高度"等
|
|
|
+- **作用域参数**:无
|
|
|
+
|
|
|
+```vue
|
|
|
+
|
|
|
+<template #toolbar>
|
|
|
+ <a-button type="primary" @click="getFormValues">获取表单数据</a-button>
|
|
|
+</template>
|
|
|
+```
|
|
|
+
|
|
|
+**源码实现**:TableHeader 中 `toolbar` 插槽渲染在右侧 `__toolbar` 区域,后面紧跟 `TableSetting` 组件。当 `toolbar` 插槽和
|
|
|
+`showTableSetting` 同时存在时,中间会自动添加竖线分隔符 `Divider`。
|
|
|
+
|
|
|
+##### 3. `headerTop` — 表头顶部区域
|
|
|
+
|
|
|
+- **位置**:表格标题栏上方,独立一行
|
|
|
+- **用途**:放置提示信息、自定义选中状态显示等
|
|
|
+- **作用域参数**:无
|
|
|
+
|
|
|
+```vue
|
|
|
+
|
|
|
+<template #headerTop>
|
|
|
+ <a-alert type="info" show-icon>
|
|
|
+ <template #message>
|
|
|
+ <template v-if="checkedKeys.length > 0">
|
|
|
+ <span>已选中{{ checkedKeys.length }}条记录(可跨页)</span>
|
|
|
+ <a-button type="link" @click="checkedKeys = []" size="small">清空</a-button>
|
|
|
+ </template>
|
|
|
+ <template v-else>
|
|
|
+ <span>未选中任何项目</span>
|
|
|
+ </template>
|
|
|
+ </template>
|
|
|
+ </a-alert>
|
|
|
+</template>
|
|
|
+```
|
|
|
+
|
|
|
+**源码实现**:TableHeader 中 `headerTop` 插槽在最顶部渲染,外层包裹 `margin: 5px` 的 div。
|
|
|
+
|
|
|
+##### 4. `tableTop` — 表头下方区域(替代默认选中提示)
|
|
|
+
|
|
|
+- **位置**:标题栏下方,默认是选中行数的 alert 提示
|
|
|
+- **用途**:自定义选中提示区域,或用空内容隐藏默认提示
|
|
|
+- **作用域参数**:无
|
|
|
+
|
|
|
+```vue
|
|
|
+<!-- 用法1:隐藏默认选中提示 -->
|
|
|
+<template #tableTop><span></span></template>
|
|
|
+
|
|
|
+<!-- 用法2:自定义选中提示内容 -->
|
|
|
+<template #tableTop>
|
|
|
+ <a-alert type="info" show-icon>
|
|
|
+ <template #message>自定义提示内容</template>
|
|
|
+ </a-alert>
|
|
|
+</template>
|
|
|
+```
|
|
|
+
|
|
|
+**源码实现**:TableHeader 中 `tableTop` 插槽有默认内容——一个 `<a-alert>` 显示"已选中 X 条记录"和"清空"链接。使用此插槽会*
|
|
|
+*完全替换**默认提示。
|
|
|
+
|
|
|
+##### 5. `alertAfter` — 选中提示后方区域
|
|
|
+
|
|
|
+- **位置**:紧跟在默认选中提示 alert 之后
|
|
|
+- **用途**:在选中提示后追加自定义内容
|
|
|
+- **作用域参数**:无
|
|
|
+
|
|
|
+**源码实现**:`alertAfter` 插槽嵌套在 `tableTop` 默认内容的 `<a-alert>` 内部,仅在选中行数 > 0 时显示。项目暂未发现实际使用案例。
|
|
|
+
|
|
|
+#### 第二类:表格内容区域插槽
|
|
|
+
|
|
|
+##### 6. `bodyCell` — 单元格内容(antdv3.x 兼容)
|
|
|
+
|
|
|
+- **位置**:表格所有单元格
|
|
|
+- **用途**:统一拦截所有单元格渲染,根据 `column.key` 判断是否自定义渲染
|
|
|
+- **作用域参数**:`{ column, record, text, index, renderIndex }`
|
|
|
+
|
|
|
+```vue
|
|
|
+
|
|
|
+<template #bodyCell="{ column, record }">
|
|
|
+ <Avatar v-if="column.key === 'avatar'" :size="60" :src="record.avatar"/>
|
|
|
+</template>
|
|
|
+```
|
|
|
+
|
|
|
+**重要机制
|
|
|
+**:[BasicTable.vue](file:///d:/Code/Project/湛江人社/code/zjrs-jeecgBoot/jeecgboot-vue3/src/components/Table/src/BasicTable.vue)
|
|
|
+中 `bodyCell` 插槽有特殊逻辑:
|
|
|
+
|
|
|
+```vue
|
|
|
+
|
|
|
+<template #bodyCell="data">
|
|
|
+ <template v-if="data.column?.slotsBak?.customRender">
|
|
|
+ <!-- 如果列配置了 slotsBak.customRender,优先使用列级自定义插槽 -->
|
|
|
+ <slot :name="data.column.slotsBak.customRender" v-bind="data || {}"></slot>
|
|
|
+ </template>
|
|
|
+ <template v-else>
|
|
|
+ <!-- 否则使用 bodyCell 插槽 -->
|
|
|
+ <slot name="bodyCell" v-bind="data || {}"></slot>
|
|
|
+ </template>
|
|
|
+</template>
|
|
|
+```
|
|
|
+
|
|
|
+即:如果列配置了 `slots.customRender`,会优先使用列级命名插槽;否则走 `bodyCell` 全局插槽。
|
|
|
+
|
|
|
+##### 7. `expandedRowRender` — 展开行内容
|
|
|
+
|
|
|
+- **位置**:点击行展开图标后显示的子内容区域
|
|
|
+- **用途**:展示子表、详情信息、嵌套表格等
|
|
|
+- **作用域参数**:`{ record, index, indent, expanded }`
|
|
|
+
|
|
|
+```vue
|
|
|
+<!-- 简单用法 -->
|
|
|
+<template #expandedRowRender="{ record }">
|
|
|
+ <span>No: {{ record.no }}</span>
|
|
|
+</template>
|
|
|
+
|
|
|
+<!-- 复杂用法 - 嵌套子表 -->
|
|
|
+<template #expandedRowRender="{ record }">
|
|
|
+ <a-tabs v-model:activeKey="innerSubTable.tabIndex">
|
|
|
+ <a-tab-pane v-for="(item, index) in innerSubTable.tabNav" :tab="item.tableTxt" :key="index + ''">
|
|
|
+ <OnlCgformInnerSubTable :subTableId="item.id" :mTableSelectedRcordId="expandedRowKeys[0]"/>
|
|
|
+ </a-tab-pane>
|
|
|
+ </a-tabs>
|
|
|
+</template>
|
|
|
+```
|
|
|
+
|
|
|
+##### 8. `summary` — 表尾合计区域
|
|
|
+
|
|
|
+- **位置**:表格底部合计行
|
|
|
+- **用途**:自定义合计行渲染,覆盖默认的 TableSummary 组件
|
|
|
+- **作用域参数**:`{ pageData }`(当前页数据)
|
|
|
+
|
|
|
+```vue
|
|
|
+
|
|
|
+<template #summary="{ pageData }">
|
|
|
+ <TableSummary fixed>
|
|
|
+ <TableSummaryRow>
|
|
|
+ <TableSummaryCell :index="0">合计</TableSummaryCell>
|
|
|
+ <TableSummaryCell :index="1">{{ totalAmount }}</TableSummaryCell>
|
|
|
+ </TableSummaryRow>
|
|
|
+ </TableSummary>
|
|
|
+</template>
|
|
|
+```
|
|
|
+
|
|
|
+**生效条件**:此插槽仅在 `showSummaryRef` 为 true(即配置了 `summaryFunc` 或 `summaryData` 且有数据)且 `showSummary` prop
|
|
|
+为 false 时生效。默认情况下使用内置 TableSummary 组件渲染。
|
|
|
+
|
|
|
+##### 9. `headerCell` — 表头单元格
|
|
|
+
|
|
|
+- **位置**:表头单元格
|
|
|
+- **用途**:自定义表头单元格渲染
|
|
|
+- **作用域参数**:`{ column, title }`
|
|
|
+
|
|
|
+**特殊处理**:当列是自定义选择列时,会渲染 `CustomSelectHeader` 而非用户自定义内容(解决全选框不显示的问题)。
|
|
|
+
|
|
|
+#### 第三类:列级自定义插槽
|
|
|
+
|
|
|
+##### 10. 列内容自定义插槽(`slots.customRender`)
|
|
|
+
|
|
|
+- **定义方式**:在列配置中设置 `slots: { customRender: 'slotName' }`
|
|
|
+- **作用域参数**:`{ text, record, column, index, renderIndex }`
|
|
|
+
|
|
|
+```typescript
|
|
|
+// 列配置
|
|
|
+const columns: BasicColumn[] = [
|
|
|
+ {title: 'ID', dataIndex: 'id', slots: {customRender: 'id'}},
|
|
|
+ {title: '编号', dataIndex: 'no', slots: {customRender: 'no'}},
|
|
|
+ {title: '图片', dataIndex: 'imgArr', slots: {customRender: 'img'}},
|
|
|
+];
|
|
|
+```
|
|
|
+
|
|
|
+```vue
|
|
|
+<!-- 对应的插槽 -->
|
|
|
+<template #id="{ record }">ID: {{ record.id }}</template>
|
|
|
+<template #no="{ record }">
|
|
|
+ <Tag color="green">{{ record.no }}</Tag>
|
|
|
+</template>
|
|
|
+<template #img="{ text }">
|
|
|
+ <TableImg :size="60" :simpleShow="true" :imgList="text"/>
|
|
|
+</template>
|
|
|
+```
|
|
|
+
|
|
|
+**Online 表单中的典型用法**:
|
|
|
+
|
|
|
+```vue
|
|
|
+<!-- 文件下载插槽 -->
|
|
|
+<template #fileSlot="{ text, record, column }">
|
|
|
+ <span v-if="!text">无文件</span>
|
|
|
+ <a-button v-else :ghost="true" type="primary" size="small" @click="downloadRowFile(text, record, column, ID)">下载
|
|
|
+ </a-button>
|
|
|
+</template>
|
|
|
+
|
|
|
+<!-- 图片预览插槽 -->
|
|
|
+<template #imgSlot="{ text }">
|
|
|
+ <span v-if="!text">无图片</span>
|
|
|
+ <img v-else :src="getImgView(text)" alt="图片不存在" class="online-cell-image"/>
|
|
|
+</template>
|
|
|
+
|
|
|
+<!-- 富文本插槽 -->
|
|
|
+<template #htmlSlot="{ text, column, record }">
|
|
|
+ <template v-if="column.fieldHref">
|
|
|
+ <a v-html="text" @click="handleClickFieldHref(column.fieldHref, record)"></a>
|
|
|
+ </template>
|
|
|
+ <div v-else v-html="text"></div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<!-- 省市区插槽 -->
|
|
|
+<template #pcaSlot="{ text, column }">
|
|
|
+ <div :title="getPcaText(text, column)">{{ getPcaText(text, column) }}</div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<!-- 日期格式化插槽 -->
|
|
|
+<template #dateSlot="{ text, column }">
|
|
|
+ <span>{{ getFormatDate(text, column) }}</span>
|
|
|
+</template>
|
|
|
+```
|
|
|
+
|
|
|
+##### 11. 列标题自定义插槽(`slots.title`)
|
|
|
+
|
|
|
+- **定义方式**:在列配置中设置 `slots: { title: 'slotName' }`
|
|
|
+- **作用域参数**:无
|
|
|
+
|
|
|
+```typescript
|
|
|
+// 列配置
|
|
|
+{
|
|
|
+ dataIndex: 'name', slots
|
|
|
+:
|
|
|
+ {
|
|
|
+ title: 'customTitle'
|
|
|
+ }
|
|
|
+}
|
|
|
+{
|
|
|
+ dataIndex: 'address', slots
|
|
|
+:
|
|
|
+ {
|
|
|
+ title: 'customAddress'
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+```vue
|
|
|
+
|
|
|
+<template #customTitle>
|
|
|
+ <span>姓名 <BasicHelp class="ml-2" text="姓名"/></span>
|
|
|
+</template>
|
|
|
+<template #customAddress>
|
|
|
+ 地址
|
|
|
+ <FormOutlined class="ml-2"/>
|
|
|
+</template>
|
|
|
+```
|
|
|
+
|
|
|
+##### 12. `action` — 操作列插槽(最常用的列级插槽)
|
|
|
+
|
|
|
+- **定义方式**:通过 `actionColumn` 配置自动生成,内部设置 `slots: { customRender: 'action' }`
|
|
|
+- **作用域参数**:`{ record, index }`
|
|
|
+
|
|
|
+```vue
|
|
|
+
|
|
|
+<template #action="{ record }">
|
|
|
+ <TableAction :actions="getTableAction(record)" :dropDownActions="getDropDownAction(record)"/>
|
|
|
+</template>
|
|
|
+```
|
|
|
+
|
|
|
+#### 第四类:搜索表单插槽
|
|
|
+
|
|
|
+##### 13. `form-xxx` — 搜索表单字段自定义插槽
|
|
|
+
|
|
|
+- **定义方式**:在 FormSchema 中配置 `slot: 'slotName'`,使用时插槽名为 `form-slotName`
|
|
|
+- **作用域参数**:`{ model, field, values }`(model 是表单数据对象,field 是字段名)
|
|
|
+
|
|
|
+```typescript
|
|
|
+// FormSchema 配置
|
|
|
+{
|
|
|
+ field: 'email', component
|
|
|
+:
|
|
|
+ 'JInput', slot
|
|
|
+:
|
|
|
+ 'email'
|
|
|
+}
|
|
|
+{
|
|
|
+ field: 'age', component
|
|
|
+:
|
|
|
+ 'JInput', slot
|
|
|
+:
|
|
|
+ 'age'
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+```vue
|
|
|
+<!-- 邮箱自定义搜索 -->
|
|
|
+<template #form-email="{ model, field }">
|
|
|
+ <a-input placeholder="请输入邮箱" v-model:value="model[field]" addon-before="邮箱:" addon-after=".com"></a-input>
|
|
|
+</template>
|
|
|
+
|
|
|
+<!-- 年龄范围搜索 -->
|
|
|
+<template #form-age="{ model, field }">
|
|
|
+ <a-input placeholder="最小年龄" type="ge" v-model:value="min" style="width: calc(50% - 15px)"
|
|
|
+ @change="ageChange(model, field)"></a-input>
|
|
|
+ <span>~</span>
|
|
|
+ <a-input placeholder="最大年龄" type="le" v-model:value="max" style="width: calc(50% - 15px)"
|
|
|
+ @change="ageChange(model, field)"></a-input>
|
|
|
+</template>
|
|
|
+```
|
|
|
+
|
|
|
+**机制说明
|
|
|
+**:[useTableForm.ts](file:///d:/Code/Project/湛江人社/code/zjrs-jeecgBoot/jeecgboot-vue3/src/components/Table/src/hooks/useTableForm.ts)
|
|
|
+中,`getFormSlotKeys` 计算属性会自动识别所有以 `form-` 开头的插槽,`replaceFormSlotKey` 函数将 `form-` 前缀去掉后映射到
|
|
|
+BasicForm 的对应插槽。
|
|
|
+
|
|
|
+#### 第五类:Ant Design 原生插槽透传
|
|
|
+
|
|
|
+`slotNamesGroup` 计算属性会将非 `bodyCell` 且非列级自定义的插槽归入 `native` 组,直接透传给底层 `<Table>` 组件。因此 Ant
|
|
|
+Design Vue Table 支持的所有原生插槽都可以直接使用,包括但不限于:
|
|
|
+
|
|
|
+| 原生插槽 | 作用域参数 | 用途 |
|
|
|
+|--------------------|----------------------------------|----------|
|
|
|
+| `headerCell` | `{ column, title }` | 自定义表头单元格 |
|
|
|
+| `customFilterIcon` | `{ filtered }` | 自定义筛选图标 |
|
|
|
+| `expandIcon` | `{ expanded, onExpand, record }` | 自定义展开图标 |
|
|
|
+| `emptyText` | 无 | 空数据提示 |
|
|
|
+
|
|
|
+### 17.3 插槽分类汇总表
|
|
|
+
|
|
|
+| 插槽名 | 类别 | 作用域参数 | 典型放置组件 | 使用频率 |
|
|
|
+|---------------------|-------|---------------------------------------|---------------------------------------------|------|
|
|
|
+| `tableTitle` | 表头区域 | 无 | a-button, a-dropdown, j-upload-button, Icon | 极高 |
|
|
|
+| `toolbar` | 表头区域 | 无 | a-button | 中 |
|
|
|
+| `headerTop` | 表头区域 | 无 | a-alert | 低 |
|
|
|
+| `tableTop` | 表头区域 | 无 | 自定义内容/空span(隐藏默认提示) | 低 |
|
|
|
+| `alertAfter` | 表头区域 | 无 | 自定义内容 | 极低 |
|
|
|
+| `bodyCell` | 表格内容 | `{ column, record, text, index }` | Avatar, Tag, 任意组件 | 中 |
|
|
|
+| `expandedRowRender` | 表格内容 | `{ record, index, indent, expanded }` | a-tabs, 子表格, 详情面板 | 中 |
|
|
|
+| `summary` | 表格内容 | `{ pageData }` | TableSummary | 低 |
|
|
|
+| `headerCell` | 表格内容 | `{ column, title }` | 自定义表头 | 低 |
|
|
|
+| `action` | 列级自定义 | `{ record, index }` | TableAction | 极高 |
|
|
|
+| 自定义列插槽 | 列级自定义 | `{ text, record, column, index }` | Tag, TableImg, a-button, img | 高 |
|
|
|
+| 自定义标题插槽 | 列级自定义 | 无 | BasicHelp, Icon, 自定义标题 | 低 |
|
|
|
+| `form-xxx` | 搜索表单 | `{ model, field, values }` | a-input, 自定义表单控件 | 中 |
|
|
|
+| Ant原生插槽 | 原生透传 | 视具体插槽而定 | 视具体插槽而定 | 低 |
|
|
|
+
|
|
|
+### 17.4 插槽中可放置的前端组件
|
|
|
+
|
|
|
+BasicTable 的插槽本质上是 Vue 的标准插槽机制,可以放置**任何合法的 Vue 组件或 HTML 内容**。项目中实际使用的组件包括:
|
|
|
+
|
|
|
+#### Ant Design Vue 组件
|
|
|
+
|
|
|
+| 组件 | 常用插槽 | 用途 |
|
|
|
+|-----------------------------------------|-----------------------------|-----------|
|
|
|
+| `a-button` | tableTitle, toolbar, action | 操作按钮(最常见) |
|
|
|
+| `a-dropdown` / `a-menu` / `a-menu-item` | tableTitle | 下拉菜单/批量操作 |
|
|
|
+| `a-alert` | headerTop, tableTop | 提示信息 |
|
|
|
+| `a-input` | form-xxx | 输入框(表单插槽) |
|
|
|
+| `a-tabs` / `a-tab-pane` | expandedRowRender | 标签页(展开行) |
|
|
|
+| `Tag` | 列自定义插槽 | 标签展示 |
|
|
|
+| `Avatar` | bodyCell | 头像展示 |
|
|
|
+| `a-divider` | tableTitle | 分隔线 |
|
|
|
+
|
|
|
+#### 项目自定义组件
|
|
|
+
|
|
|
+| 组件 | 常用插槽 | 用途 |
|
|
|
+|--------------------------|---------------------|---------------------------|
|
|
|
+| `TableAction` | action | 操作列组件(配合 action 插槽使用,最核心) |
|
|
|
+| `TableImg` | 列自定义插槽 | 图片展示组件 |
|
|
|
+| `BasicHelp` | 列标题插槽 | 帮助提示组件 |
|
|
|
+| `Icon` | tableTitle, toolbar | 图标组件 |
|
|
|
+| `j-upload-button` | tableTitle | 上传按钮 |
|
|
|
+| `OnlineSuperQuery` | tableTitle | 高级查询组件 |
|
|
|
+| `OnlCgformInnerSubTable` | expandedRowRender | 子表组件 |
|
|
|
+| `import-excel-progress` | tableTitle | 导入进度组件 |
|
|
|
+
|
|
|
+#### 原生 HTML
|
|
|
+
|
|
|
+- `span`, `div`, `img`, `a` 等基础标签
|
|
|
+- `v-html` 渲染富文本内容
|
|
|
+
|
|
|
+#### 任意自定义 Vue 组件
|
|
|
+
|
|
|
+只要是合法的 Vue 组件,都可以放入插槽中使用。
|
|
|
+
|
|
|
+### 17.5 插槽使用代码规范
|
|
|
+
|
|
|
+#### 规范一:操作按钮统一放在 `tableTitle` 插槽
|
|
|
+
|
|
|
+```vue
|
|
|
+<!-- ✅ 推荐 -->
|
|
|
+<BasicTable @register="registerTable" :rowSelection="rowSelection">
|
|
|
+ <template #tableTitle>
|
|
|
+ <a-button type="primary" v-auth="'xxx:add'" preIcon="ant-design:plus-outlined" @click="handleAdd">新增</a-button>
|
|
|
+ <a-button type="primary" v-auth="'xxx:export'" preIcon="ant-design:export-outlined" @click="onExportXls">导出
|
|
|
+ </a-button>
|
|
|
+ <j-upload-button type="primary" v-auth="'xxx:import'" preIcon="ant-design:import-outlined" @click="onImportXls">
|
|
|
+ 导入
|
|
|
+ </j-upload-button>
|
|
|
+ </template>
|
|
|
+</BasicTable>
|
|
|
+
|
|
|
+<!-- ❌ 不推荐:操作按钮放在其他位置 -->
|
|
|
+```
|
|
|
+
|
|
|
+#### 规范二:操作列统一使用 `action` 插槽 + `TableAction` 组件
|
|
|
+
|
|
|
+```vue
|
|
|
+<!-- ✅ 推荐 -->
|
|
|
+<template #action="{ record }">
|
|
|
+ <TableAction :actions="getTableAction(record)" :dropDownActions="getDropDownAction(record)"/>
|
|
|
+</template>
|
|
|
+
|
|
|
+<!-- ❌ 不推荐:在 action 插槽中直接写按钮 -->
|
|
|
+<template #action="{ record }">
|
|
|
+ <a-button @click="handleEdit(record)">编辑</a-button>
|
|
|
+ <a-button @click="handleDelete(record)">删除</a-button>
|
|
|
+</template>
|
|
|
+```
|
|
|
+
|
|
|
+#### 规范三:列自定义渲染优先使用 `slots.customRender` 而非 `bodyCell`
|
|
|
+
|
|
|
+```typescript
|
|
|
+// ✅ 推荐:使用列级插槽,语义清晰
|
|
|
+{
|
|
|
+ title: '状态', dataIndex
|
|
|
+:
|
|
|
+ 'status', slots
|
|
|
+:
|
|
|
+ {
|
|
|
+ customRender: 'status'
|
|
|
+ }
|
|
|
+}
|
|
|
+// 对应模板: <template #status="{ record }">...</template>
|
|
|
+
|
|
|
+// ❌ 不推荐:使用 bodyCell 全局拦截,所有列都在一个插槽中判断
|
|
|
+// <template #bodyCell="{ column, record }">
|
|
|
+// <template v-if="column.key === 'status'">...</template>
|
|
|
+// <template v-if="column.key === 'type'">...</template>
|
|
|
+// </template>
|
|
|
+```
|
|
|
+
|
|
|
+#### 规范四:搜索表单自定义控件使用 `form-xxx` 插槽
|
|
|
+
|
|
|
+```typescript
|
|
|
+// data.ts 中定义
|
|
|
+{
|
|
|
+ field: 'age', component
|
|
|
+:
|
|
|
+ 'JInput', slot
|
|
|
+:
|
|
|
+ 'age'
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+```vue
|
|
|
+<!-- 列表页中使用 -->
|
|
|
+<template #form-age="{ model, field }">
|
|
|
+ <a-input v-model:value="model[field]" placeholder="请输入年龄"/>
|
|
|
+</template>
|
|
|
+```
|
|
|
+
|
|
|
+#### 规范五:隐藏默认选中提示时使用空 `tableTop` 插槽
|
|
|
+
|
|
|
+```vue
|
|
|
+<!-- 隐藏默认的"已选中X条记录"提示 -->
|
|
|
+<template #tableTop><span></span></template>
|
|
|
+```
|
|
|
+
|
|
|
+#### 规范六:批量操作按钮使用 `a-dropdown` 并条件显示
|
|
|
+
|
|
|
+```vue
|
|
|
+
|
|
|
+<template #tableTitle>
|
|
|
+ <!-- 其他按钮... -->
|
|
|
+ <a-dropdown v-if="selectedRowKeys.length > 0">
|
|
|
+ <template #overlay>
|
|
|
+ <a-menu>
|
|
|
+ <a-menu-item key="1" @click="batchHandleDelete">
|
|
|
+ <Icon icon="ant-design:delete-outlined"></Icon>
|
|
|
+ 删除
|
|
|
+ </a-menu-item>
|
|
|
+ </a-menu>
|
|
|
+ </template>
|
|
|
+ <a-button>批量操作
|
|
|
+ <Icon icon="mdi:chevron-down"></Icon>
|
|
|
+ </a-button>
|
|
|
+ </a-dropdown>
|
|
|
+</template>
|
|
|
+```
|
|
|
+
|
|
|
+#### 规范七:按钮权限控制
|
|
|
+
|
|
|
+```vue
|
|
|
+<!-- 使用 v-auth 指令 -->
|
|
|
+<a-button type="primary" v-auth="'spbb:sppb_video:add'" @click="handleAdd">新增</a-button>
|
|
|
+
|
|
|
+<!-- 在 TableAction 中使用 auth 属性 -->
|
|
|
+function getTableAction(record): ActionItem[] {
|
|
|
+return [
|
|
|
+{ label: '编辑', onClick: handleEdit.bind(null, record), auth: 'spbb:sppb_video:edit' },
|
|
|
+];
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### 17.6 关键源码索引(BasicTable 插槽)
|
|
|
+
|
|
|
+| 文件 | 作用 |
|
|
|
+|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------|
|
|
|
+| [BasicTable.vue](file:///d:/Code/Project/湛江人社/code/zjrs-jeecgBoot/jeecgboot-vue3/src/components/Table/src/BasicTable.vue) | 主组件,定义插槽透传逻辑和 slotNamesGroup 分类 |
|
|
|
+| [useTableHeader.ts](file:///d:/Code/Project/湛江人社/code/zjrs-jeecgBoot/jeecgboot-vue3/src/components/Table/src/hooks/useTableHeader.ts) | 处理表头区域插槽传递给 TableHeader |
|
|
|
+| [useTableForm.ts](file:///d:/Code/Project/湛江人社/code/zjrs-jeecgBoot/jeecgboot-vue3/src/components/Table/src/hooks/useTableForm.ts) | 处理 form-xxx 插槽的识别和前缀替换 |
|
|
|
+| [TableHeader.vue](file:///d:/Code/Project/湛江人社/code/zjrs-jeecgBoot/jeecgboot-vue3/src/components/Table/src/components/TableHeader.vue) | 表头布局组件,渲染 headerTop/tableTitle/toolbar/tableTop/alertAfter |
|
|
|
+| [CustomerCell.vue](file:///d:/Code/Project/湛江人社/code/zjrs-jeecgBoot/jeecgboot-vue3/src/views/demo/table/CustomerCell.vue) | 列自定义插槽 + bodyCell 使用示例 |
|
|
|
+| [ExpandTable.vue](file:///d:/Code/Project/湛江人社/code/zjrs-jeecgBoot/jeecgboot-vue3/src/views/demo/table/ExpandTable.vue) | expandedRowRender 使用示例 |
|
|
|
+| [FormTable.vue](file:///d:/Code/Project/湛江人社/code/zjrs-jeecgBoot/jeecgboot-vue3/src/views/demo/table/FormTable.vue) | headerTop/toolbar/form-xxx 使用示例 |
|
|
|
+| [BasicTableDemoAjax.vue](file:///d:/Code/Project/湛江人社/code/zjrs-jeecgBoot/jeecgboot-vue3/src/views/demo/document/table/BasicTableDemoAjax.vue) | form-email 自定义搜索示例 |
|
|
|
+| [OnlCgformInnerTableList.vue](file:///d:/Code/Project/湛江人社/code/zjrs-jeecgBoot/jeecgboot-vue3/src/views/super/online/cgform/auto/innerTable/OnlCgformInnerTableList.vue) | expandedRowRender + Online 列插槽综合示例 |
|