diff --git a/examples/views/grid/Footer.vue b/examples/views/grid/Footer.vue index c4533d68df..1129138b91 100644 --- a/examples/views/grid/Footer.vue +++ b/examples/views/grid/Footer.vue @@ -41,6 +41,7 @@ export default defineComponent({ const gridOptions = reactive({ border: true, stripe: true, + aboveBodyFooter: true, resizable: true, showFooter: true, height: 400, diff --git a/examples/views/table/advanced/Footer.vue b/examples/views/table/advanced/Footer.vue index 942f102a80..8c8c5d38fb 100644 --- a/examples/views/table/advanced/Footer.vue +++ b/examples/views/table/advanced/Footer.vue @@ -67,6 +67,7 @@ show-overflow class="mytable-footer" height="400" + above-body-footer :show-header="demo3.showHeader" :show-footer="demo3.showFooter" :footer-method="footerMethod" diff --git a/packages/table/src/props.ts b/packages/table/src/props.ts index 81e643c288..d1985702fe 100644 --- a/packages/table/src/props.ts +++ b/packages/table/src/props.ts @@ -48,6 +48,8 @@ export default { highlightCell: Boolean as PropType, // 是否显示表尾合计 showFooter: Boolean as PropType, + // 表尾放到 body 上方 + aboveBodyFooter: Boolean as PropType, // 表尾合计的计算方法 footerMethod: Function as PropType, // 给行附加 className diff --git a/packages/table/src/table.ts b/packages/table/src/table.ts index b259e177c7..7441a98ddc 100644 --- a/packages/table/src/table.ts +++ b/packages/table/src/table.ts @@ -1455,7 +1455,7 @@ export default defineComponent({ } const updateStyle = () => { - const { border, showFooter, showOverflow: allColumnOverflow, showHeaderOverflow: allColumnHeaderOverflow, showFooterOverflow: allColumnFooterOverflow, mouseConfig, spanMethod, footerSpanMethod, keyboardConfig } = props + const { border, showFooter, aboveBodyFooter, showOverflow: allColumnOverflow, showHeaderOverflow: allColumnHeaderOverflow, showFooterOverflow: allColumnFooterOverflow, mouseConfig, spanMethod, footerSpanMethod, keyboardConfig } = props const { isGroup, currentRow, tableColumn, scrollXLoad, scrollYLoad, scrollbarWidth, scrollbarHeight, columnStore, editStore, mergeList, mergeFooterList, isAllOverflow } = reactData let { visibleColumn, fullColumnIdData, tableHeight, tableWidth, headerHeight, footerHeight, elemStore, customHeight, customMinHeight, customMaxHeight } = internalData const containerList = ['main', 'left', 'right'] @@ -1466,11 +1466,12 @@ export default defineComponent({ const bodyWrapperRef = elemStore['main-body-wrapper'] const bodyWrapperElem = bodyWrapperRef ? bodyWrapperRef.value : null if (emptyPlaceholderElem) { - emptyPlaceholderElem.style.top = `${headerHeight}px` + // emptyPlaceholderElem.style.top = `${headerHeight}px` + emptyPlaceholderElem.style.top = `${headerHeight + ((showFooter && aboveBodyFooter) ? footerHeight : 0)}px` emptyPlaceholderElem.style.height = bodyWrapperElem ? `${bodyWrapperElem.offsetHeight - scrollbarHeight}px` : '' } if (customHeight > 0) { - if (showFooter) { + if (showFooter && !aboveBodyFooter) { customHeight += scrollbarHeight } } @@ -1569,10 +1570,14 @@ export default defineComponent({ // 如果是固定列 if (fixedWrapperElem) { + let fixedHeight = 0 if (isNodeElement(wrapperElem)) { - wrapperElem.style.top = `${headerHeight}px` + if (showFooter && aboveBodyFooter) { + fixedHeight = Math.max(wrapperElem.offsetHeight - wrapperElem.clientHeight - scrollbarHeight, 0) + } + wrapperElem.style.top = showFooter && aboveBodyFooter ? `${(customHeight > 0 ? customHeight - footerHeight + scrollbarHeight - fixedHeight : headerHeight + footerHeight - scrollbarHeight * 2)}px` : `${headerHeight}px` } - fixedWrapperElem.style.height = `${(customHeight > 0 ? customHeight - headerHeight - footerHeight : tableHeight) + headerHeight + footerHeight - scrollbarHeight * (showFooter ? 2 : 1)}px` + fixedWrapperElem.style.height = `${(customHeight > 0 ? customHeight - headerHeight - footerHeight : tableHeight) + headerHeight + footerHeight - scrollbarHeight * (showFooter ? 2 : 1) - fixedHeight}px` fixedWrapperElem.style.width = `${fixedColumn.reduce((previous, column) => previous + column.renderWidth, isFixedLeft ? 0 : scrollbarWidth)}px` } @@ -1624,7 +1629,7 @@ export default defineComponent({ if (isNodeElement(wrapperElem)) { // 如果是固定列 if (fixedWrapperElem) { - wrapperElem.style.top = `${customHeight > 0 ? customHeight - footerHeight : tableHeight + headerHeight}px` + wrapperElem.style.top = aboveBodyFooter ? `${headerHeight}px` : `${customHeight > 0 ? customHeight - footerHeight : tableHeight + headerHeight}px` } wrapperElem.style.marginTop = `${-Math.max(1, scrollbarHeight)}px` } @@ -6092,7 +6097,7 @@ export default defineComponent({ * @param {String} fixedType 固定列类型 */ const renderFixed = (fixedType: 'left' | 'right') => { - const { showHeader, showFooter } = props + const { showHeader, showFooter, aboveBodyFooter } = props const { tableData, tableColumn, tableGroupColumn, columnStore, footerTableData } = reactData const isFixedLeft = fixedType === 'left' const fixedColumn = isFixedLeft ? columnStore.leftList : columnStore.rightList @@ -6108,6 +6113,15 @@ export default defineComponent({ tableGroupColumn, fixedColumn }) : createCommentVNode(), + + aboveBodyFooter ? (showFooter ? h(TableFooterComponent, { + ref: isFixedLeft ? refTableLeftFooter : refTableRightFooter, + footerTableData, + tableColumn, + fixedColumn, + fixedType + }) : createCommentVNode()) : createCommentVNode(), + h(TableBodyComponent as ComponentOptions, { ref: isFixedLeft ? refTableLeftBody : refTableRightBody, fixedType, @@ -6115,17 +6129,17 @@ export default defineComponent({ tableColumn, fixedColumn }), - showFooter ? h(TableFooterComponent, { + showFooter ? (!aboveBodyFooter ? h(TableFooterComponent, { ref: isFixedLeft ? refTableLeftFooter : refTableRightFooter, footerTableData, tableColumn, fixedColumn, fixedType - }) : createCommentVNode() + }) : createCommentVNode()) : createCommentVNode() ]) } - const renderEmptyContenet = () => { + const renderEmptyContent = () => { const emptyOpts = computeEmptyOpts.value const params = { $table: $xetable } if (slots.empty) { @@ -6512,7 +6526,7 @@ export default defineComponent({ }) const renderVN = () => { - const { loading, stripe, showHeader, height, treeConfig, mouseConfig, showFooter, highlightCell, highlightHoverRow, highlightHoverColumn, editConfig, editRules } = props + const { loading, stripe, showHeader, height, treeConfig, mouseConfig, showFooter, aboveBodyFooter, highlightCell, highlightHoverRow, highlightHoverColumn, editConfig, editRules } = props const { isGroup, overflowX, overflowY, scrollXLoad, scrollYLoad, scrollbarHeight, tableData, tableColumn, tableGroupColumn, footerTableData, initStore, columnStore, filterStore } = reactData const { leftList, rightList } = columnStore const loadingSlot = slots.loading @@ -6541,6 +6555,7 @@ export default defineComponent({ 'column--highlight': columnOpts.isHover || highlightHoverColumn, 'is--header': showHeader, 'is--footer': showFooter, + 'is--above-body-footer': aboveBodyFooter, 'is--group': isGroup, 'is--tree-line': treeConfig && (treeOpts.showLine || treeOpts.line), 'is--fixed-left': leftList.length, @@ -6578,6 +6593,16 @@ export default defineComponent({ tableColumn, tableGroupColumn }) : createCommentVNode(), + + /** + * 表尾 + */ + aboveBodyFooter ? (showFooter ? h(TableFooterComponent, { + ref: refTableFooter, + footerTableData, + tableColumn + }) : createCommentVNode()) : createCommentVNode(), + /** * 表体 */ @@ -6589,11 +6614,11 @@ export default defineComponent({ /** * 表尾 */ - showFooter ? h(TableFooterComponent, { + showFooter ? (!aboveBodyFooter ? h(TableFooterComponent, { ref: refTableFooter, footerTableData, tableColumn - }) : createCommentVNode() + }) : createCommentVNode()) : createCommentVNode() ]), h('div', { class: 'vxe-table--fixed-wrapper' @@ -6617,7 +6642,7 @@ export default defineComponent({ }, [ h('div', { class: 'vxe-table--empty-content' - }, renderEmptyContenet()) + }, renderEmptyContent()) ]), /** * 边框线 diff --git a/styles/table.scss b/styles/table.scss index da7ee03261..768e24857e 100644 --- a/styles/table.scss +++ b/styles/table.scss @@ -658,7 +658,7 @@ user-select: none; } } - + /*边框*/ .vxe-table--footer-wrapper { border-top: var(--vxe-table-border-width) solid var(--vxe-table-border-color); @@ -736,7 +736,7 @@ display: none; } } - + &.size--medium { font-size: var(--vxe-font-size-medium); .vxe-table--empty-placeholder, @@ -1352,6 +1352,13 @@ } } } + + /*above body footer*/ + &.is--above-body-footer { + .vxe-table--footer-wrapper.body--wrapper { + overflow: hidden; + } + } } /*valid error*/ @@ -1389,4 +1396,4 @@ div.vxe-table--tooltip-wrapper { } } } -} \ No newline at end of file +} diff --git a/types/table.d.ts b/types/table.d.ts index 81cbfd2b2a..08c5663595 100644 --- a/types/table.d.ts +++ b/types/table.d.ts @@ -1151,6 +1151,7 @@ export namespace VxeTablePropTypes { export type HighlightHoverColumn = boolean export type HighlightCell = boolean export type ShowFooter = boolean + export type AboveBodyFooter = boolean; export type FooterMethod = (params: { $table: VxeTableConstructor & VxeTablePrivateMethods @@ -2425,6 +2426,10 @@ export type VxeTableProps = { * 是否显示表尾 */ showFooter?: VxeTablePropTypes.ShowFooter + /** + * 表尾放在body上方 + */ + aboveBodyFooter?: VxeTablePropTypes.AboveBodyFooter /** * 表尾的数据获取方法,返回一个二维数组 */