feat: table support summary

pull/4639/head
tangjinzhou 2021-09-09 23:16:08 +08:00
parent 9693d89342
commit 16e801249c
18 changed files with 366 additions and 74 deletions

View File

@ -172,7 +172,14 @@ export type {
ColumnProps as TableColumnProps,
ColumnsType as TableColumnsType,
} from './table';
export { default as Table, TableColumn, TableColumnGroup } from './table';
export {
default as Table,
TableColumn,
TableColumnGroup,
TableSummary,
TableSummaryRow,
TableSummaryCell,
} from './table';
export type { TransferProps } from './transfer';
export { default as Transfer } from './transfer';

View File

@ -1,7 +1,7 @@
import { defineComponent } from 'vue';
import type { ColumnType } from './interface';
export type ColumnProps = ColumnType;
export type ColumnProps<RecordType = unknown> = ColumnType<RecordType>;
export default defineComponent<ColumnProps>({
name: 'ATableColumn',
slots: ['title', 'filterIcon'],

View File

@ -489,7 +489,9 @@ const InteralTable = defineComponent<
return classNames(
{
[`${prefixCls}-row-selected`]: selectedKeySet.value.has(getRowKey.value(record, index)),
[`${prefixCls.value}-row-selected`]: selectedKeySet.value.has(
getRowKey.value(record, index),
),
},
mergedRowClassName,
);
@ -645,11 +647,4 @@ const Table = defineComponent<TableProps>({
},
});
Table.SELECTION_ALL = SELECTION_ALL;
Table.SELECTION_INVERT = SELECTION_INVERT;
Table.SELECTION_NONE = SELECTION_NONE;
Table.Column = Column;
Table.ColumnGroup = ColumnGroup;
Table.Summary = Summary;
export default Table;

View File

@ -20,9 +20,6 @@ Ellipsis cell content via setting `column.ellipsis`.
<template>
<a-table :columns="columns" :data-source="data">
<template #name="{ text }">
<a>{{ text }}</a>
</template>
<template #bodyCell="{ column, text }">
<template v-if="column.dataIndex === 'name'">
<a>{{ text }}</a>
@ -38,7 +35,6 @@ const columns = [
title: 'Name',
dataIndex: 'name',
key: 'name',
slots: { customRender: 'name' },
},
{
title: 'Age',

View File

@ -15,6 +15,7 @@
<FixedHeader />
<GroupingColumns />
<Head />
<MultipleSorter />
<NestedTable />
<ResetFilter />
<RowSelectionAndOperation />
@ -22,6 +23,7 @@
<RowSelection />
<Size />
<Stripe />
<Summary />
<TemplateCom />
</demo-sort>
</template>
@ -51,6 +53,8 @@ import Size from './size.vue';
import TemplateCom from './template.vue';
import Ellipsis from './ellipsis.vue';
import Stripe from './stripe.vue';
import MultipleSorter from './multiple-sorter.vue';
import Summary from './summary.vue';
import CN from '../index.zh-CN.md';
import US from '../index.en-US.md';
@ -81,6 +85,8 @@ export default {
Size,
TemplateCom,
Stripe,
MultipleSorter,
Summary,
},
};
</script>

View File

@ -0,0 +1,99 @@
<docs>
---
order: 7
title:
en-US: Multiple sorter
zh-CN: 多列排序
---
## zh-CN
`column.sorter` 支持 `multiple` 字段以配置多列排序优先级通过 `sorter.compare` 配置排序逻辑你可以通过不设置该函数只启动多列排序的交互形式
## en-US
`column.sorter` support `multiple` to config the priority of sort columns. Though `sorter.compare` to customize compare function. You can also leave it empty to use the interactive only.
</docs>
<template>
<a-table :columns="columns" :data-source="data" @change="onChange" />
</template>
<script lang="ts">
import { defineComponent } from 'vue';
const columns = [
{
title: 'Name',
dataIndex: 'name',
},
{
title: 'Chinese Score',
dataIndex: 'chinese',
sorter: {
compare: (a, b) => a.chinese - b.chinese,
multiple: 3,
},
},
{
title: 'Math Score',
dataIndex: 'math',
sorter: {
compare: (a, b) => a.math - b.math,
multiple: 2,
},
},
{
title: 'English Score',
dataIndex: 'english',
sorter: {
compare: (a, b) => a.english - b.english,
multiple: 1,
},
},
];
const data = [
{
key: '1',
name: 'John Brown',
chinese: 98,
math: 60,
english: 70,
},
{
key: '2',
name: 'Jim Green',
chinese: 98,
math: 66,
english: 89,
},
{
key: '3',
name: 'Joe Black',
chinese: 98,
math: 90,
english: 70,
},
{
key: '4',
name: 'Jim Red',
chinese: 88,
math: 99,
english: 89,
},
];
export default defineComponent({
setup() {
return {
data,
columns,
onChange: (pagination, filters, sorter, extra) => {
console.log('params', pagination, filters, sorter, extra);
},
};
},
});
</script>

View File

@ -37,9 +37,8 @@ To perform operations and clear selections after selecting some rows, use `rowSe
</template>
<script lang="ts">
import { computed, defineComponent, reactive, toRefs } from 'vue';
import { ColumnProps } from 'ant-design-vue/es/table/interface';
type Key = ColumnProps['key'];
type Key = string | number;
interface DataType {
key: Key;

View File

@ -19,12 +19,10 @@ Use `rowSelection.selections` custom selections, default no select dropdown, sho
</template>
<script lang="ts">
import { defineComponent, computed, ref, unref } from 'vue';
import { ColumnProps } from 'ant-design-vue/es/table/interface';
type Key = ColumnProps['key'];
import { Table } from 'ant-design-vue';
interface DataType {
key: Key;
key: string | number;
name: string;
age: number;
address: string;
@ -57,9 +55,9 @@ for (let i = 0; i < 46; i++) {
export default defineComponent({
setup() {
const selectedRowKeys = ref<Key[]>([]); // Check here to configure the default column
const selectedRowKeys = ref<DataType['key'][]>([]); // Check here to configure the default column
const onSelectChange = (changableRowKeys: Key[]) => {
const onSelectChange = (changableRowKeys: string[]) => {
console.log('selectedRowKeys changed: ', changableRowKeys);
selectedRowKeys.value = changableRowKeys;
};
@ -70,19 +68,15 @@ export default defineComponent({
onChange: onSelectChange,
hideDefaultSelections: true,
selections: [
{
key: 'all-data',
text: 'Select All Data',
onSelect: () => {
selectedRowKeys.value = [...Array(46).keys()]; // 0...45
},
},
Table.SELECTION_ALL,
Table.SELECTION_INVERT,
Table.SELECTION_NONE,
{
key: 'odd',
text: 'Select Odd Row',
onSelect: (changableRowKeys: Key[]) => {
onSelect: changableRowKeys => {
let newSelectedRowKeys = [];
newSelectedRowKeys = changableRowKeys.filter((key, index) => {
newSelectedRowKeys = changableRowKeys.filter((_key, index) => {
if (index % 2 !== 0) {
return false;
}
@ -94,9 +88,9 @@ export default defineComponent({
{
key: 'even',
text: 'Select Even Row',
onSelect: (changableRowKeys: Key[]) => {
onSelect: changableRowKeys => {
let newSelectedRowKeys = [];
newSelectedRowKeys = changableRowKeys.filter((key, index) => {
newSelectedRowKeys = changableRowKeys.filter((_key, index) => {
if (index % 2 !== 0) {
return true;
}

View File

@ -18,29 +18,29 @@ selection happens when clicking checkbox defaultly. You can see https://codesand
<template>
<a-table :row-selection="rowSelection" :columns="columns" :data-source="data">
<template #name="{ text }">
<a>{{ text }}</a>
<template #bodyCell="{ column, text }">
<template v-if="column.dataIndex === 'name'">
<a>{{ text }}</a>
</template>
<template v-else>{{ text }}</template>
</template>
</a-table>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { ColumnProps } from 'ant-design-vue/es/table/interface';
type Key = ColumnProps['key'];
import type { TableProps, TableColumnType } from 'ant-design-vue';
interface DataType {
key: Key;
key: string;
name: string;
age: number;
address: string;
}
const columns = [
const columns: TableColumnType<DataType>[] = [
{
title: 'Name',
dataIndex: 'name',
slots: { customRender: 'name' },
},
{
title: 'Age',
@ -80,8 +80,8 @@ const data: DataType[] = [
export default defineComponent({
setup() {
const rowSelection = {
onChange: (selectedRowKeys: Key[], selectedRows: DataType[]) => {
const rowSelection: TableProps['rowSelection'] = {
onChange: (selectedRowKeys: string[], selectedRows: DataType[]) => {
console.log(`selectedRowKeys: ${selectedRowKeys}`, 'selectedRows: ', selectedRows);
},
getCheckboxProps: (record: DataType) => ({

View File

@ -0,0 +1,158 @@
<docs>
---
order: 29
title:
en-US: Summary
zh-CN: 总结栏
---
## zh-CN
通过 `summary` 设置总结栏使用 `a-table-summary-cell` 同步 Column 的固定状态你可以通过配置 `a-table-summary` `fixed` 属性使其固定
## en-US
Set summary content by `summary` prop. Sync column fixed status with `a-table-summary-cell`. You can fixed it by set `a-table-summary` `fixed` prop.
</docs>
<template>
<a-table :columns="columns" :data-source="data" :pagination="false" bordered>
<template #summary>
<a-table-summary-row>
<a-table-summary-cell>Total</a-table-summary-cell>
<a-table-summary-cell>
<a-typography-text type="danger">{{ totals.totalBorrow }}</a-typography-text>
</a-table-summary-cell>
<a-table-summary-cell>
<a-typography-text>{{ totals.totalRepayment }}</a-typography-text>
</a-table-summary-cell>
</a-table-summary-row>
<a-table-summary-row>
<a-table-summary-cell>Balance</a-table-summary-cell>
<a-table-summary-cell :col-span="2">
<a-typography-text type="danger">
{{ totals.totalBorrow - totals.totalRepayment }}
</a-typography-text>
</a-table-summary-cell>
</a-table-summary-row>
</template>
</a-table>
<a-table
:columns="fixedColumns"
:data-source="fixedData"
:pagination="false"
:scroll="{ x: 2000, y: 500 }"
bordered
>
<template #summary>
<a-table-summary fixed>
<a-table-summary-row>
<a-table-summary-cell :index="0">Summary</a-table-summary-cell>
<a-table-summary-cell :index="1">This is a summary content</a-table-summary-cell>
</a-table-summary-row>
</a-table-summary>
</template>
</a-table>
</template>
<script lang="ts">
import { computed, defineComponent, ref } from 'vue';
export default defineComponent({
setup() {
const columns = ref([
{
title: 'Name',
dataIndex: 'name',
},
{
title: 'Borrow',
dataIndex: 'borrow',
},
{
title: 'Repayment',
dataIndex: 'repayment',
},
]);
const data = ref([
{
key: '1',
name: 'John Brown',
borrow: 10,
repayment: 33,
},
{
key: '2',
name: 'Jim Green',
borrow: 100,
repayment: 0,
},
{
key: '3',
name: 'Joe Black',
borrow: 10,
repayment: 10,
},
{
key: '4',
name: 'Jim Red',
borrow: 75,
repayment: 45,
},
]);
const fixedColumns = ref([
{
title: 'Name',
dataIndex: 'name',
fixed: true,
width: 100,
},
{
title: 'Description',
dataIndex: 'description',
},
]);
const fixedData = ref<{ key: number; name: string; description: string }[]>([]);
for (let i = 0; i < 20; i += 1) {
fixedData.value.push({
key: i,
name: ['Light', 'Bamboo', 'Little'][i % 3],
description: 'Everything that has a beginning, has an end.',
});
}
const totals = computed(() => {
let totalBorrow = 0;
let totalRepayment = 0;
data.value.forEach(({ borrow, repayment }) => {
totalBorrow += borrow;
totalRepayment += repayment;
});
return { totalBorrow, totalRepayment };
});
return {
data,
columns,
totals,
fixedColumns,
fixedData,
};
},
});
</script>
<style>
#components-table-demo-summary tfoot th,
#components-table-demo-summary tfoot td {
background: #fafafa;
}
[data-theme='dark'] #components-table-demo-summary tfoot th,
[data-theme='dark'] #components-table-demo-summary tfoot td {
background: #1d1d1d;
}
</style>

View File

@ -1,27 +1,67 @@
import Table, { tableProps } from './Table';
import type Column from './Column';
import type ColumnGroup from './ColumnGroup';
import Column from './Column';
import ColumnGroup from './ColumnGroup';
import type { TableProps, TablePaginationConfig } from './Table';
import type { App } from 'vue';
import { App, defineComponent } from 'vue';
import { Summary, SummaryCell, SummaryRow } from '../vc-table';
import { SELECTION_ALL, SELECTION_INVERT, SELECTION_NONE } from './hooks/useSelection';
export type { ColumnProps } from './Column';
export type { ColumnsType, ColumnType, ColumnGroupType } from './interface';
export type { TableProps, TablePaginationConfig };
const TableSummaryRow = defineComponent({ ...SummaryRow, name: 'ATableSummaryRow' });
const TableSummaryCell = defineComponent({ ...SummaryCell, name: 'ATableSummaryCell' });
const TempSummary = defineComponent({
...Summary,
name: 'ATableSummary',
});
const TableSummary = TempSummary as typeof TempSummary & {
Cell: typeof TableSummaryCell;
Row: typeof TableSummaryRow;
};
TableSummary.Cell = TableSummaryCell;
TableSummary.Row = TableSummaryRow;
const T = Table as typeof Table &
Plugin & {
Column: typeof Column;
ColumnGroup: typeof ColumnGroup;
Summary: typeof TableSummary;
SELECTION_ALL: typeof SELECTION_ALL;
SELECTION_INVERT: typeof SELECTION_INVERT;
SELECTION_NONE: typeof SELECTION_NONE;
};
T.SELECTION_ALL = SELECTION_ALL;
T.SELECTION_INVERT = SELECTION_INVERT;
T.SELECTION_NONE = SELECTION_NONE;
T.Column = Column;
T.ColumnGroup = ColumnGroup;
T.Summary = TableSummary;
/* istanbul ignore next */
Table.install = function (app: App) {
app.component(Table.name, Table);
app.component(Table.Column.name, Table.Column);
app.component(Table.ColumnGroup.name, Table.ColumnGroup);
T.install = function (app: App) {
app.component(TableSummary.name, TableSummary);
app.component(TableSummaryCell.name, TableSummaryCell);
app.component(TableSummaryRow.name, TableSummaryRow);
app.component(T.name, T);
app.component(T.Column.name, Column);
app.component(T.ColumnGroup.name, ColumnGroup);
return app;
};
export const TableColumn = Table.Column;
export const TableColumnGroup = Table.ColumnGroup;
export { tableProps };
export {
tableProps,
TableSummary,
TableSummaryRow,
TableSummaryCell,
Column as TableColumn,
ColumnGroup as TableColumnGroup,
};
export default Table as typeof Table &
Plugin & {
readonly Column: typeof Column;
readonly ColumnGroup: typeof ColumnGroup;
};
export default T;

View File

@ -109,7 +109,7 @@ export default defineComponent<CellProps>({
align,
rowType,
isSticky,
column,
column = {},
cellType,
} = props;
const cellPrefixCls = `${prefixCls}-cell`;

View File

@ -20,7 +20,7 @@ export default defineComponent<SummaryCellProps>({
const tableContext = useInjectTable();
const summaryContext = useInjectSummary();
return () => {
const { index, colSpan, rowSpan, align } = props;
const { index, colSpan = 1, rowSpan, align } = props;
const { prefixCls, direction } = tableContext;
const { scrollColumnIndex, stickyOffsets, flattenColumns } = summaryContext;
const lastIndex = index + colSpan - 1;
@ -33,7 +33,6 @@ export default defineComponent<SummaryCellProps>({
stickyOffsets,
direction,
);
return (
<Cell
class={attrs.class as string}
@ -44,7 +43,7 @@ export default defineComponent<SummaryCellProps>({
dataIndex={null}
align={align}
customRender={() => ({
children: slots.defalut?.(),
children: slots.default?.(),
props: {
colSpan: mergedColSpan,
rowSpan,

View File

@ -1,7 +1,5 @@
import { computed, defineComponent, onBeforeUnmount, watchEffect } from 'vue';
import { useInjectTable } from '../context/TableContext';
import Cell from './Cell';
import Row from './Row';
export interface SummaryProps {
fixed?: boolean | 'top' | 'bottom';
@ -11,8 +9,6 @@ let indexGuid = 0;
const Summary = defineComponent<SummaryProps>({
props: ['fixed'] as any,
name: 'Summary',
Row,
Cell,
setup(props, { slots }) {
const tableContext = useInjectTable();
const uniKey = `table-summary-uni-key-${++indexGuid}`;

View File

@ -1,4 +1,6 @@
import Summary from './Summary';
import SummaryRow from './Row';
import SummaryCell from './Cell';
import type { DefaultRecordType, StickyOffsets } from '../interface';
import { computed, defineComponent, reactive, toRef } from 'vue';
import type { FlattenColumns } from '../context/SummaryContext';
@ -34,4 +36,5 @@ export default defineComponent({
},
});
export { SummaryRow, SummaryCell };
export const FooterComponents = Summary;

View File

@ -332,7 +332,7 @@ export default defineComponent<TableProps>({
const summaryFixedInfos = reactive<Record<string, boolean | string>>({});
const fixFooter = computed(() => {
const info = Object.values(summaryFixedInfos)[0];
return fixHeader.value || (stickyState.value.isSticky && info);
return (fixHeader.value || stickyState.value.isSticky) && info;
});
const summaryCollect = (uniKey: string, fixed: boolean | string) => {
@ -568,7 +568,7 @@ export default defineComponent<TableProps>({
stickyState.value;
const TableComponent = getComponent(['table'], 'table');
const summaryNode = slots.summary?.();
const summaryNode = slots.summary?.({ pageData: mergedData.value });
let groupTableNode;
@ -703,7 +703,7 @@ export default defineComponent<TableProps>({
{bodyContent}
{/* Summary Table */}
{fixFooter.value !== 'top' && (
{fixFooter.value && fixFooter.value !== 'top' && (
<FixedHolder
{...fixedHolderProps}
stickyBottomOffset={offsetSummary}

View File

@ -1,10 +1,10 @@
// base rc-table@7.17.2
import Table from './Table';
import { FooterComponents as Summary } from './Footer';
import { FooterComponents as Summary, SummaryCell, SummaryRow } from './Footer';
import Column from './sugar/Column';
import ColumnGroup from './sugar/ColumnGroup';
import { INTERNAL_COL_DEFINE } from './utils/legacyUtil';
export { Summary, Column, ColumnGroup, INTERNAL_COL_DEFINE };
export { Summary, Column, ColumnGroup, SummaryCell, SummaryRow, INTERNAL_COL_DEFINE };
export default Table;

View File

@ -1,5 +1,5 @@
// debugger tsx
import Demo from '../../components/table/demo/template.vue';
import Demo from '../../components/table/demo/summary.vue';
export default {
render() {