feat(table): 实现动态表格列配置功能

This commit is contained in:
2026-02-06 15:49:17 +08:00
parent 2e2e2a0819
commit 0bc2decff5
3 changed files with 64 additions and 50 deletions
@@ -36,31 +36,45 @@
@selection-change="onTableSelectionChange" @selection-change="onTableSelectionChange"
> >
<el-table-column v-if="showSelect" type="selection" width="55" /> <el-table-column v-if="showSelect" type="selection" width="55" />
<slot /> <el-table-column
<el-pagination v-for="column in crud.columns"
v-if="paging" :key="column.name"
:current-page="pageProps.current" :prop="column.name"
:page-sizes="[10, 20, 50]" :label="column.title"
:page-size="pageProps.pageSize" :width="column.width ? column.width : null"
layout="total, sizes, prev, pager, next" :sortable="column.sortable === true ? `custom` : false"
:total="pageProps.total" >
@size-change="(size) => crud.onPageChange(pageProps.current, size, pageProps.total)" <template v-slot="scope">
@current-change="(current) => crud.onPageChange(current, pageProps.pageSize, pageProps.total)" <div v-if="column.cell && column.cell instanceof Function">
/> {{ column.cell(scope.row[column.name], scope.$index, scope.row) }}
</el-table></div> </div>
<div v-else>
{{ scope.row[column.name] }}
</div>
</template>
</el-table-column>
<!-- 通过 <template v-slot:operation> 插槽后置操作按钮 -->
<slot name="operation" />
</el-table>
<el-pagination
v-if="paging"
:current-page="pageProps.current"
:page-sizes="[10, 20, 50]"
:page-size="pageProps.pageSize"
layout="total, sizes, prev, pager, next"
:total="pageProps.total"
@size-change="(size) => crud.onPageChange(pageProps.current, size, pageProps.total)"
@current-change="(current) => crud.onPageChange(current, pageProps.pageSize, pageProps.total)"
/>
</div>
</template> </template>
<script> <script>
import Sortable from 'sortablejs' import Sortable from 'sortablejs'
export default { export default {
name: 'CuteDragTable', name: 'CuteDynamicTable',
props: { props: {
primaryKey: {
type: String,
required: true,
default: 'id'
},
fetch: { fetch: {
type: Function, type: Function,
required: false, required: false,
@@ -102,8 +116,9 @@ export default {
return { return {
crud: { crud: {
loading: false, loading: false,
primaryKey: this.primaryKey ? this.primaryKey : 'id', primaryKey: 'id',
fetchUrl: null, fetchUrl: null,
columns: [],
dataSource: [], dataSource: [],
onPageChange: (currentPage, pageSize) => { onPageChange: (currentPage, pageSize) => {
this.pageProps.current = currentPage this.pageProps.current = currentPage
@@ -126,7 +141,7 @@ export default {
}, },
methods: { methods: {
refresh() { refresh() {
this.crud.orderBy = '' // this.crud.orderBy = null
this.crud.selection = [] this.crud.selection = []
this.initData() this.initData()
this.initDragTable() this.initDragTable()
@@ -144,21 +159,22 @@ export default {
if (this.fetch) { if (this.fetch) {
try { try {
this.crud.loading = true this.crud.loading = true
// 请求远程数据 // 请求远程数据 { primaryKey: 'id', columns: [], totalElements: 0, content: []}
const response = await this.fetch(params) let transformData = await this.fetch(params)
// console.error('response', response)
// { content: [], totalElements: 0 }
// 转换为表格所需要的数据 // 转换为表格所需要的数据
if (this.responseTransform) { if (this.responseTransform) {
return this.responseTransform(response) transformData = this.responseTransform(transformData)
if (!transformData.primaryKey) {
transformData.primaryKey = 'id'
}
} }
if (response && response.hasOwnProperty('totalElements') && response.hasOwnProperty('content')) { // if (response && response.hasOwnProperty('totalElements') && response.hasOwnProperty('content')) {
this.pageProps.total = response.totalElements this.pageProps.total = transformData.totalElements
this.crud.dataSource = response.content this.crud.primaryKey = transformData.primaryKey
} this.crud.columns = transformData.columns
return response this.crud.dataSource = transformData.content
} catch (e) { } catch (e) {
console.error('CuteDragTable请求远程数据异常', e) console.error('CuteDynamicable请求远程数据异常', e)
this.pageProps.total = 0 this.pageProps.total = 0
this.crud.dataSource = [] this.crud.dataSource = []
} finally { } finally {
@@ -3,7 +3,8 @@
<h4>何时使用</h4> <h4>何时使用</h4>
<ul class="description"> <ul class="description">
<li>展示结构化数据列表,并支持排序、分页、拖拽排序</li> <li>展示结构化数据列表,并支持排序、分页、拖拽排序</li>
<li>在使用过程中有任何问题,咨询 @Odboy(前端)</li> <li>由后端统一返回前端所需的字段</li>
<li>在使用过程中有任何问题,咨询 @Odboy(前端)@Odboy(后端)</li>
</ul> </ul>
<h4>基础用法</h4> <h4>基础用法</h4>
<!-- 表格渲染 --> <!-- 表格渲染 -->
@@ -13,11 +14,17 @@
<!-- showSelect: 是否多选。不传默认false,传true为多选 --> <!-- showSelect: 是否多选。不传默认false,传true为多选 -->
<!-- @selection-change: 当且仅当mode为multi时启用 --> <!-- @selection-change: 当且仅当mode为multi时启用 -->
<!-- @order-change: 当排序字段被单击,el-table-column 需添加 sortable="custom" 属性 --> <!-- @order-change: 当排序字段被单击,el-table-column 需添加 sortable="custom" 属性 -->
<cute-search-form :model="form" @search="handleSearch">
<template v-slot:suffix>
<el-form-item label="菜单标题" prop="blurry">
<el-input v-model="form.blurry" clearable />
</el-form-item>
</template>
</cute-search-form>
<cute-dynamic-table <cute-dynamic-table
ref="instance" ref="instance"
:fetch="curd.fetch" :fetch="curd.fetch"
:params-transform="curd.paramsTransform" :params-transform="curd.paramsTransform"
:page-props="curd.pageProps"
show-select show-select
> >
<template v-slot:batchArea> <template v-slot:batchArea>
@@ -57,12 +64,12 @@
<script> <script>
import FeatureCuteDynamicTableService from '@/api/features/cute-dynamic-table' import FeatureCuteDynamicTableService from '@/api/features/cute-dynamic-table'
import CuteButton from '@/views/components/dev/CuteButton.vue' import CuteButton from '@/views/components/dev/CuteButton.vue'
import { FormatRowDateTimeStr } from '@/utils/KitUtil'
import CuteDynamicTable from '@/views/components/advanced/CuteDynamicTable.vue' import CuteDynamicTable from '@/views/components/advanced/CuteDynamicTable.vue'
import CuteSearchForm from '@/views/components/advanced/CuteSearchForm.vue'
export default { export default {
name: 'CuteDynamicTableDemo', name: 'CuteDynamicTableDemo',
components: { CuteDynamicTable, CuteButton }, components: { CuteSearchForm, CuteDynamicTable, CuteButton },
data() { data() {
return { return {
form: { form: {
@@ -81,17 +88,6 @@ export default {
}, },
fetch: async(queryParams) => { fetch: async(queryParams) => {
return FeatureCuteDynamicTableService.searchMenu(queryParams) return FeatureCuteDynamicTableService.searchMenu(queryParams)
},
columns: [
{ prop: 'name', label: '名称' },
{ prop: 'description', label: '描述' },
{ prop: 'createTime', label: '创建时间', formatter: FormatRowDateTimeStr },
{ prop: 'createBy', label: '创建人' }
],
pageProps: {
current: 1,
pageSize: 10,
total: 0
} }
}, },
apiData: [ apiData: [
@@ -117,10 +113,12 @@ export default {
this.refreshData() this.refreshData()
}, },
methods: { methods: {
FormatRowDateTimeStr,
refreshData() { refreshData() {
this.$refs.instance.refresh() this.$refs.instance.refresh()
}, },
handleSearch() {
this.$refs.instance.refresh()
},
onTableEditClick(row) { onTableEditClick(row) {
console.log('编辑', row) console.log('编辑', row)
}, },
@@ -28,11 +28,11 @@ public class SystemMenuDynamicTableModel extends KitObject {
private Long id; private Long id;
@KitDynamicTableColumn(value = "菜单标题") @KitDynamicTableColumn(value = "菜单标题")
private String title; private String title;
@KitDynamicTableColumn(value = "菜单组件名称") @KitDynamicTableColumn(value = "菜单组件名称", width = 200)
private String componentName; private String componentName;
@KitDynamicTableColumn(value = "排序") @KitDynamicTableColumn(value = "排序")
private Integer menuSort = 999; private Integer menuSort = 999;
@KitDynamicTableColumn(value = "组件路径", width = 240) @KitDynamicTableColumn(value = "组件路径", width = 200)
private String component; private String component;
@KitDynamicTableColumn(value = "路由地址", width = 120) @KitDynamicTableColumn(value = "路由地址", width = 120)
private String path; private String path;
@@ -48,7 +48,7 @@ public class SystemMenuDynamicTableModel extends KitObject {
private Boolean hidden; private Boolean hidden;
@KitDynamicTableColumn(value = "上级菜单") @KitDynamicTableColumn(value = "上级菜单")
private Long pid; private Long pid;
@KitDynamicTableColumn(value = "子节点数目", sortable = true) @KitDynamicTableColumn(value = "子节点数目", sortable = true, width = 200)
private Integer subCount = 0; private Integer subCount = 0;
@KitDynamicTableColumn(value = "外链菜单") @KitDynamicTableColumn(value = "外链菜单")
private Boolean iFrame; private Boolean iFrame;