antdvue的table合计行
vue3+antdvue使用a-table合计行
·
在开发后台管理系统中,经常会碰到合计行的需求,element有直接的属性可以使用,antdvue的需要手动去生成
https://www.antdv.com/components/table-cn/#components-table-demo-summary
如图为实现合计后的效果
1。首先给table配置column的时候,要明确哪些字段需要使用合计,如上图,只有总板数需要使用合计,那给总板数的配置加上标识符 即可,我这里为了方便辨识,直接增加了 summary:true
{ title: '总板数', resizable: true, dataIndex: 'totalBoard', width: 150, align: 'center', ellipsis: true, summary: true },
2.搭好基础结构,直接上代码
2.1当需要合计时才去遍历表格数据使用reduce计算总合计数量
<template #summary>
<a-table-summary fixed>
<a-table-summary-row>
<a-table-summary-cell :index="0"> 合计</a-table-summary-cell>
<a-table-summary-cell v-for="(item, index) in columns" :key="index" :index="1">
// 当列配置了summary为true才合计
<template v-if="item?.summary">
<a-typography-text>
{{ dataSource.reduce((prev: number, next: : any }) => {
return prev + next.totalBoard
}, 0)}}
</a-typography-text>
</template>
</a-table-summary-cell>
</a-table-summary-row>
</a-table-summary>
</template>
2.2代码优化
当字段为动态时,并且模板里写太多ts语法看起来太臃肿,所以抽成计算属性更好维护
// 模板
<template #summary>
<a-table-summary fixed>
<a-table-summary-row>
<a-table-summary-cell :index="0"> 合计</a-table-summary-cell>
<a-table-summary-cell v-for="(item, index) in contentTableParam.columns" :key="index" :index="1">
<template v-if="item?.summary">
<a-typography-text>
{{ combinedNums(item.dataIndex) }}
</a-typography-text>
</template>
</a-table-summary-cell>
</a-table-summary-row>
</a-table-summary>
</template>
/**
* @returns 计算合计行
*/
const combinedNums = computed(() => (field: any) => {
return contentTableParam.dataSource.reduce((prev: number, next: { [x: string]: any }) => {
return prev + next[field]
}, 0)
})
组件抽取部分
首先组件封装思路:因为业务的表格涉及到部分表格开启了选择框,部分未开启,选择框会坐固定,所以要分两种情况来判断
1.组件需要接收的参数ts类型
import type { TablePaginationConfig } from 'ant-design-vue'
import type { Rule } from 'ant-design-vue/es/form'
export type ColumnType = {
title: string // 标题
dataIndex?: string // 列数据在数据项中对应的路径
key?: string // Vue 需要的 key,如果已经设置了唯一的 dataIndex,可以忽略这个属性
resizable?: boolean // 是否可拖动调整宽度,此时 width 必须是 number 类型
width: number // 列宽度
align?: string // 对齐方式
ellipsis?: boolean // 超过宽度将自动省略
sorter?: boolean // 开启排序
sortDirections?: Array<string> // 支持的排序方式,取值为 'ascend' 'descend'
summary?: boolean // 是否开启列合计
fixed?: 'left' | 'right' // 对其方式
}
export type interContentTable = {
name?: string // 使用Table排序必填
isOper: boolean // table扩展项
rowSelection?: boolean // 是否开启选择框
rowSelectionType?: 'radio' | 'checkbox' // 是否开启选择框
tableConfig?: boolean // table排序
loading?: boolean
rowKey: string // key
isCalcHeight?: boolean // table高度自适应
selectedRowKeys?: Array<string | number> // 选中key
pagination?: TablePaginationConfig
columns: ColumnType[]
dataSource: Record<string, any>[]
}
2.组件template和ts代码
<template>
<!-- 如果开启了选择框,则遍历列 -->
<template v-if="origin.rowSelection">
<a-table-summary fixed>
<a-table-summary-row>
<a-table-summary-cell :index="0"> 合计</a-table-summary-cell>
// 注意,因为table列的对齐方式可配置并且选择框默认占一列,所以这里的index一定要跟i+1相同才可以保证合计列和配置了对齐方式之后的列依然在一列上
<a-table-summary-cell v-for="(item, index) in origin.columns" :key="item.dataIndex" :index="index + 1">
<template v-if="item?.summary">
<a-typography-text>
{{ combinedNums(item.dataIndex).toFixed(3) }}
</a-typography-text>
</template>
</a-table-summary-cell>
</a-table-summary-row>
</a-table-summary>
</template>
<!-- 如果未开启选择框,循环长度 -->
<template v-if="!origin.rowSelection">
<a-table-summary fixed>
<a-table-summary-row>
// 注意,因为table列的对齐方式可配置,所以 这里的index一定要跟i相同才可以保证合计列和配置了对齐方式之后的列依然在一列上
<a-table-summary-cell :index="0"> 合计</a-table-summary-cell>
<a-table-summary-cell v-for="i in origin.columns.length" :key="i" :index="i">
<template v-if="origin.columns[i]?.summary">
<a-typography-text>
{{ combinedNums(origin.columns[i].dataIndex).toFixed(3) }}
</a-typography-text>
</template>
</a-table-summary-cell>
</a-table-summary-row>
</a-table-summary>
</template>
</template>
<script setup lang="ts">
import { interContentTable } from '@/type/interface/content'
import { withDefaults, computed } from 'vue'
interface propsType {
origin: interContentTable
}
const _props = withDefaults(defineProps<propsType>(), {
origin: () => ({ isOper: false, loading: false, rowKey: '', columns: [], dataSource: [] }),
})
/**
* @returns 计算合计行
*/
const combinedNums = computed(() => (field: any) => {
return _props.origin.dataSource.reduce((prev: number, next: { [x: string]: any }) => {
return prev + Number(next[field])
}, 0)
})
</script>
<style scoped lang="less"></style>
3.使用组件
<a-table>
<template #summary>
<TemplateSummary :origin="contentTableParam" />
</template>
</a-table>
<script setup lang="ts" name="goDownPlanList">
import { ref, reactive, getCurrentInstance, nextTick, computed, Ref, onActivated } from 'vue'
import TemplateSummary from '@/components/template-summary/index.vue'
import type { ColumnType } from '@/type/interface/content'
const contentTableParam = reactive({
isOper: true,
emptyText: true, // 是否自定义空数据展示
rowSelection: true, // 选择框
rowKey: 'id',
columnWidth: 80,
selectedRowKeys: [] as string[],
name: 'GODOWNPLAN_LIST_MAIN',
tableConfig: true, // 表单配置
isCalcHeight: true, // 是否自动计算table高度
loading: false,
isSlotOption: ['summary'],
pagination: {
pageSize: 20,
total: 0,
current: 1,
},
scroll: {
scrollToFirstRowOnChange: false,
y: 300,
},
columns: [
{ title: '单号', dataIndex: 'planCode', resizable: true, width: 250, align: 'center', ellipsis: true },
{ title: '状态', resizable: true, key: 'statusName', dataIndex: 'statusName', width: 120, align: 'center', ellipsis: true },
{ title: '类型', resizable: true, dataIndex: 'typeName', width: 150, align: 'center', ellipsis: true },
{ title: '仓库', key: 'warehouse', dataIndex: 'warehouseCode', resizable: true, width: 200, align: 'center', ellipsis: true },
{ title: '货主', resizable: true, key: 'cargoOwner', dataIndex: 'cargoOwnerCode', width: 230, align: 'center', ellipsis: true },
{ title: '操作', key: 'operation', fixed: 'right', width: 150, align: 'center' },
] as ColumnType[],
dataSource: [],
})
</script>
更多推荐
已为社区贡献1条内容
所有评论(0)