diff --git a/examples/views/table/TableTest8.vue b/examples/views/table/TableTest8.vue index 882d7f224b..a3cb962934 100644 --- a/examples/views/table/TableTest8.vue +++ b/examples/views/table/TableTest8.vue @@ -1,97 +1,187 @@ diff --git a/examples/views/table/TableTest9.vue b/examples/views/table/TableTest9.vue index 9d87047142..9c42e7bc9b 100644 --- a/examples/views/table/TableTest9.vue +++ b/examples/views/table/TableTest9.vue @@ -1,52 +1,194 @@ diff --git a/package.json b/package.json index 12f97c9243..581e3c1308 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vxe-table", - "version": "4.7.97", + "version": "4.8.0-beta.0", "description": "一个基于 vue 的 PC 端表格组件,支持增删改查、虚拟树、列拖拽,懒加载、快捷菜单、数据校验、树形结构、打印、导入导出、自定义模板、渲染器、JSON 配置式...", "scripts": { "update": "npm install --legacy-peer-deps", @@ -28,7 +28,7 @@ "style": "lib/style.css", "typings": "types/index.d.ts", "dependencies": { - "vxe-pc-ui": "^4.2.32" + "vxe-pc-ui": "^4.2.34" }, "devDependencies": { "@types/resize-observer-browser": "^0.1.11", diff --git a/packages/locale/lang/ja-JP.ts b/packages/locale/lang/ja-JP.ts index a501d0c9e8..235dbe352e 100644 --- a/packages/locale/lang/ja-JP.ts +++ b/packages/locale/lang/ja-JP.ts @@ -607,11 +607,11 @@ export default { clearSort: '清除排序', sortAsc: '升序', sortDesc: '降序', - fixedColumn: '锁定列', - fixedGroup: '锁定组', - cancelFixed: '取消锁定', - fixedLeft: '锁定左侧', - fixedRight: '锁定右侧', + fixedColumn: '冻结列', + fixedGroup: '冻结分组', + cancelFixed: '取消冻结', + fixedLeft: '冻结到左侧', + fixedRight: '冻结到右侧', clearFilter: '清除筛选', textOption: '文本筛选', numberOption: '数值筛选' diff --git a/packages/locale/lang/ko-KR.ts b/packages/locale/lang/ko-KR.ts index 4848af1f7e..7948ca28b8 100644 --- a/packages/locale/lang/ko-KR.ts +++ b/packages/locale/lang/ko-KR.ts @@ -648,11 +648,11 @@ export default { clearSort: '清除排序', sortAsc: '升序', sortDesc: '降序', - fixedColumn: '锁定列', - fixedGroup: '锁定组', - cancelFixed: '取消锁定', - fixedLeft: '锁定左侧', - fixedRight: '锁定右侧', + fixedColumn: '冻结列', + fixedGroup: '冻结分组', + cancelFixed: '取消冻结', + fixedLeft: '冻结到左侧', + fixedRight: '冻结到右侧', clearFilter: '清除筛选', textOption: '文本筛选', numberOption: '数值筛选' diff --git a/packages/locale/lang/uk-UA.ts b/packages/locale/lang/uk-UA.ts index 4848af1f7e..7948ca28b8 100644 --- a/packages/locale/lang/uk-UA.ts +++ b/packages/locale/lang/uk-UA.ts @@ -648,11 +648,11 @@ export default { clearSort: '清除排序', sortAsc: '升序', sortDesc: '降序', - fixedColumn: '锁定列', - fixedGroup: '锁定组', - cancelFixed: '取消锁定', - fixedLeft: '锁定左侧', - fixedRight: '锁定右侧', + fixedColumn: '冻结列', + fixedGroup: '冻结分组', + cancelFixed: '取消冻结', + fixedLeft: '冻结到左侧', + fixedRight: '冻结到右侧', clearFilter: '清除筛选', textOption: '文本筛选', numberOption: '数值筛选' diff --git a/packages/locale/lang/vi-VN.ts b/packages/locale/lang/vi-VN.ts index 4848af1f7e..7948ca28b8 100644 --- a/packages/locale/lang/vi-VN.ts +++ b/packages/locale/lang/vi-VN.ts @@ -648,11 +648,11 @@ export default { clearSort: '清除排序', sortAsc: '升序', sortDesc: '降序', - fixedColumn: '锁定列', - fixedGroup: '锁定组', - cancelFixed: '取消锁定', - fixedLeft: '锁定左侧', - fixedRight: '锁定右侧', + fixedColumn: '冻结列', + fixedGroup: '冻结分组', + cancelFixed: '取消冻结', + fixedLeft: '冻结到左侧', + fixedRight: '冻结到右侧', clearFilter: '清除筛选', textOption: '文本筛选', numberOption: '数值筛选' diff --git a/packages/locale/lang/zh-CHT.ts b/packages/locale/lang/zh-CHT.ts index 28c8d9c3f2..86e287f3e2 100644 --- a/packages/locale/lang/zh-CHT.ts +++ b/packages/locale/lang/zh-CHT.ts @@ -648,11 +648,11 @@ export default { clearSort: '清除排序', sortAsc: '升序', sortDesc: '降序', - fixedColumn: '鎖定列', - fixedGroup: '鎖定組', - cancelFixed: '取消鎖定', - fixedLeft: '鎖定左側', - fixedRight: '鎖定右側', + fixedColumn: '冻结列', + fixedGroup: '冻结分组', + cancelFixed: '取消冻结', + fixedLeft: '冻结到左侧', + fixedRight: '冻结到右侧', clearFilter: '清除篩選', textOption: '文字篩選', numberOption: '數值篩選' diff --git a/packages/locale/lang/zh-CN.ts b/packages/locale/lang/zh-CN.ts index 4848af1f7e..7948ca28b8 100644 --- a/packages/locale/lang/zh-CN.ts +++ b/packages/locale/lang/zh-CN.ts @@ -648,11 +648,11 @@ export default { clearSort: '清除排序', sortAsc: '升序', sortDesc: '降序', - fixedColumn: '锁定列', - fixedGroup: '锁定组', - cancelFixed: '取消锁定', - fixedLeft: '锁定左侧', - fixedRight: '锁定右侧', + fixedColumn: '冻结列', + fixedGroup: '冻结分组', + cancelFixed: '取消冻结', + fixedLeft: '冻结到左侧', + fixedRight: '冻结到右侧', clearFilter: '清除筛选', textOption: '文本筛选', numberOption: '数值筛选' diff --git a/packages/table/module/edit/hook.ts b/packages/table/module/edit/hook.ts index d5eccc4ae2..50df68984e 100644 --- a/packages/table/module/edit/hook.ts +++ b/packages/table/module/edit/hook.ts @@ -86,7 +86,7 @@ hooks.add('tableEditModule', { } parentChilds[funcName](item) mapChilds[funcName](item) - const rest = { row: item, rowid, seq: -1, index: -1, _index: -1, $index: -1, items: parentChilds, parent: parentRow, level: parentLevel + 1 } + const rest = { row: item, rowid, seq: -1, index: -1, _index: -1, $index: -1, items: parentChilds, parent: parentRow, level: parentLevel + 1, height: 0 } fullDataRowIdData[rowid] = rest fullAllDataRowIdData[rowid] = rest } else { @@ -97,7 +97,7 @@ hooks.add('tableEditModule', { } afterFullData[funcName](item) tableFullTreeData[funcName](item) - const rest = { row: item, rowid, seq: -1, index: -1, _index: -1, $index: -1, items: tableFullTreeData, parent: null, level: 0 } + const rest = { row: item, rowid, seq: -1, index: -1, _index: -1, $index: -1, items: tableFullTreeData, parent: null, level: 0, height: 0 } fullDataRowIdData[rowid] = rest fullAllDataRowIdData[rowid] = rest } @@ -172,7 +172,7 @@ hooks.add('tableEditModule', { targetIndex = targetIndex + 1 } parentMapChilds.splice(targetIndex, 0, item) - const rest = { row: item, rowid, seq: -1, index: -1, _index: -1, $index: -1, items: parentMapChilds, parent: parentRow, level: parentLevel + 1 } + const rest = { row: item, rowid, seq: -1, index: -1, _index: -1, $index: -1, items: parentMapChilds, parent: parentRow, level: parentLevel + 1, height: 0 } fullDataRowIdData[rowid] = rest fullAllDataRowIdData[rowid] = rest }) diff --git a/packages/table/render/index.ts b/packages/table/render/index.ts index c323d4549e..a9330625c3 100644 --- a/packages/table/render/index.ts +++ b/packages/table/render/index.ts @@ -13,7 +13,7 @@ const { getConfig, renderer, getI18n } = VxeUI const componentDefaultModelProp = 'modelValue' -const defaultCompProps = { transfer: true } +const defaultCompProps = {} function parseDate (value: any, props: any) { return value && props.valueFormat ? XEUtils.toStringDate(value, props.valueFormat) : value diff --git a/packages/table/src/body.ts b/packages/table/src/body.ts index f203baee61..8d7e550bb0 100644 --- a/packages/table/src/body.ts +++ b/packages/table/src/body.ts @@ -1,8 +1,8 @@ import { createCommentVNode, defineComponent, h, ref, Ref, PropType, inject, nextTick, ComputedRef, onBeforeUnmount, onMounted, onUnmounted } from 'vue' import XEUtils from 'xe-utils' import { VxeUI } from '../../ui' -import { mergeBodyMethod, getRowid, removeScrollListener, restoreScrollListener, XEBodyScrollElement } from './util' -import { updateCellTitle, getPropClass } from '../../ui/src/dom' +import { mergeBodyMethod, getRowid, XEBodyScrollElement } from './util' +import { updateCellTitle, getPropClass, setScrollTop, setScrollLeft } from '../../ui/src/dom' import { isEnableConf } from '../../ui/src/utils' import { getSlotVNs } from '../../ui/src/vn' @@ -35,7 +35,7 @@ export default defineComponent({ const xesize = inject('xesize', null as ComputedRef | null) const { xID, props: tableProps, context: tableContext, reactData: tableReactData, internalData: tableInternalData } = $xeTable - const { refTableHeader, refTableBody, refTableFooter, refTableLeftBody, refTableRightBody, refValidTooltip } = $xeTable.getRefMaps() + const { refTableBody, refTableHeader, refTableFooter, refTableLeftBody, refTableRightBody, refScrollXHandleElem, refScrollYHandleElem } = $xeTable.getRefMaps() const { computeEditOpts, computeMouseOpts, computeSYOpts, computeEmptyOpts, computeKeyboardOpts, computeTooltipOpts, computeRadioOpts, computeExpandOpts, computeTreeOpts, computeCheckboxOpts, computeValidOpts, computeRowOpts, computeColumnOpts } = $xeTable.getComputeMaps() const refElem = ref() as Ref @@ -130,8 +130,9 @@ export default defineComponent({ * 渲染列 */ const renderColumn = (seq: number | string, rowid: string, fixedType: any, rowLevel: number, row: any, rowIndex: number, $rowIndex: number, _rowIndex: number, column: any, $columnIndex: number, columns: any, items: any[]) => { + const { fullAllDataRowIdData } = tableInternalData const { columnKey, height, showOverflow: allColumnOverflow, cellClassName: allCellClassName, cellStyle, align: allAlign, spanMethod, mouseConfig, editConfig, editRules, tooltipConfig } = tableProps - const { tableData, overflowX, scrollYLoad, currentColumn, mergeList, editStore, isAllOverflow, validErrorMaps } = tableReactData + const { tableData, overflowX, currentColumn, scrollYLoad, mergeList, editStore, isAllOverflow, validErrorMaps } = tableReactData const { afterFullData } = tableInternalData const validOpts = computeValidOpts.value const checkboxOpts = computeCheckboxOpts.value @@ -155,12 +156,13 @@ export default defineComponent({ const isEdit = isEnableConf(editRender) let fixedHiddenColumn = fixedType ? column.fixed !== fixedType : column.fixed && overflowX const cellOverflow = (XEUtils.isUndefined(showOverflow) || XEUtils.isNull(showOverflow)) ? allColumnOverflow : showOverflow - let showEllipsis = cellOverflow === 'ellipsis' + const showEllipsis = cellOverflow === 'ellipsis' const showTitle = cellOverflow === 'title' const showTooltip = cellOverflow === true || cellOverflow === 'tooltip' - let hasEllipsis = showTitle || showTooltip || showEllipsis + const hasEllipsis = showTitle || showTooltip || showEllipsis let isDirty const tdOns: any = {} + const rest = fullAllDataRowIdData[rowid] const cellAlign = align || (compConf ? compConf.tableCellAlign : '') || allAlign const errorValidItem = validErrorMaps[`${rowid}:${colid}`] const showValidTip = editRules && validOpts.showMessage && (validOpts.message === 'default' ? (height || tableData.length > 1) : validOpts.message === 'inline') @@ -187,10 +189,6 @@ export default defineComponent({ data: tableData, items } - // 虚拟滚动不支持动态高度 - if (scrollYLoad && !hasEllipsis) { - showEllipsis = hasEllipsis = true - } // hover 进入事件 if (showTitle || showTooltip || showAllTip || tooltipConfig) { tdOns.onMouseenter = (evnt: MouseEvent) => { @@ -348,7 +346,7 @@ export default defineComponent({ key: columnKey || columnOpts.useKey ? colid : $columnIndex, ...attrs, style: Object.assign({ - height: hasEllipsis && (scrollYRHeight || rowHeight) ? `${scrollYRHeight || rowHeight}px` : '' + height: hasEllipsis && (scrollYRHeight || rowHeight) ? `${scrollYRHeight || rowHeight}px` : (scrollYLoad ? `${rest.height || scrollYRHeight || rowHeight}px` : '') }, XEUtils.isFunction(compCellStyle) ? compCellStyle(params) : compCellStyle, XEUtils.isFunction(cellStyle) ? cellStyle(params) : cellStyle), ...tdOns }, tdVNs) @@ -488,51 +486,6 @@ export default defineComponent({ return rows } - /** - * 同步滚动条 - */ - let scrollProcessTimeout: any - const syncBodyScroll = (fixedType: VxeColumnPropTypes.Fixed, scrollTop: number, elem1: XEBodyScrollElement | null, elem2: XEBodyScrollElement | null) => { - if (elem1 || elem2) { - if (elem1) { - removeScrollListener(elem1) - elem1.scrollTop = scrollTop - } - if (elem2) { - removeScrollListener(elem2) - elem2.scrollTop = scrollTop - } - clearTimeout(scrollProcessTimeout) - scrollProcessTimeout = setTimeout(() => { - // const tableBody = refTableBody.value - // const leftBody = refTableLeftBody.value - // const rightBody = refTableRightBody.value - // const bodyElem = tableBody.$el as XEBodyScrollElement - // const leftElem = leftBody ? leftBody.$el as XEBodyScrollElement : null - // const rightElem = rightBody ? rightBody.$el as XEBodyScrollElement : null - restoreScrollListener(elem1) - restoreScrollListener(elem2) - // 检查滚动条是的同步 - // let targetTop = bodyElem.scrollTop - // if (fixedType === 'left') { - // if (leftElem) { - // targetTop = leftElem.scrollTop - // } - // } else if (fixedType === 'right') { - // if (rightElem) { - // targetTop = rightElem.scrollTop - // } - // } - // setScrollTop(bodyElem, targetTop) - // setScrollTop(leftElem, targetTop) - // setScrollTop(rightElem, targetTop) - tableReactData.lastScrollTime = Date.now() - }, 300) - } - } - - const scrollLoadingTime: any = null - /** * 滚动处理 * 如果存在列固定左侧,同步更新滚动状态 @@ -540,98 +493,60 @@ export default defineComponent({ */ const scrollEvent = (evnt: Event) => { const { fixedType } = props - const { highlightHoverRow } = tableProps - const { scrollXLoad, scrollYLoad } = tableReactData - const { elemStore, lastScrollTop, lastScrollLeft } = tableInternalData - const rowOpts = computeRowOpts.value + const { lastScrollTop, lastScrollLeft } = tableInternalData const tableHeader = refTableHeader.value const tableBody = refTableBody.value const tableFooter = refTableFooter.value const leftBody = refTableLeftBody.value const rightBody = refTableRightBody.value - const validTip = refValidTooltip.value const scrollBodyElem = refElem.value const headerElem = tableHeader ? tableHeader.$el as HTMLDivElement : null const footerElem = tableFooter ? tableFooter.$el as HTMLDivElement : null const bodyElem = tableBody.$el as XEBodyScrollElement const leftElem = leftBody ? leftBody.$el as XEBodyScrollElement : null const rightElem = rightBody ? rightBody.$el as XEBodyScrollElement : null - const bodyYRef = elemStore['main-body-ySpace'] - const bodyYElem = bodyYRef ? bodyYRef.value : null - const bodyXRef = elemStore['main-body-xSpace'] - const bodyXElem = bodyXRef ? bodyXRef.value : null - const bodyHeight = scrollYLoad && bodyYElem ? bodyYElem.clientHeight : bodyElem.clientHeight - const bodyWidth = scrollXLoad && bodyXElem ? bodyXElem.clientWidth : bodyElem.clientWidth - let scrollTop = scrollBodyElem.scrollTop + const scrollTop = scrollBodyElem.scrollTop const scrollLeft = bodyElem.scrollLeft const isRollX = scrollLeft !== lastScrollLeft const isRollY = scrollTop !== lastScrollTop - tableInternalData.lastScrollTop = scrollTop - tableInternalData.lastScrollLeft = scrollLeft - tableReactData.lastScrollTime = Date.now() - if (rowOpts.isHover || highlightHoverRow) { - $xeTable.clearHoverRow() - } - if (leftElem && fixedType === 'left') { - scrollTop = leftElem.scrollTop - syncBodyScroll(fixedType, scrollTop, bodyElem, rightElem) - } else if (rightElem && fixedType === 'right') { - scrollTop = rightElem.scrollTop - syncBodyScroll(fixedType, scrollTop, bodyElem, leftElem) - } else { - if (isRollX) { - if (headerElem) { - headerElem.scrollLeft = bodyElem.scrollLeft - } - if (footerElem) { - footerElem.scrollLeft = bodyElem.scrollLeft - } - } - if (leftElem || rightElem) { - $xeTable.checkScrolling() - if (isRollY) { - syncBodyScroll(fixedType, scrollTop, leftElem, rightElem) - } + const xHandleEl = refScrollXHandleElem.value + const yHandleEl = refScrollYHandleElem.value + if (yHandleEl) { + yHandleEl.scrollTop = scrollTop + } else if (isRollY) { + tableInternalData.lastScrollTop = scrollTop + tableInternalData.lastScrollLeft = scrollLeft + if (leftElem && fixedType === 'left') { + setScrollTop(bodyElem, scrollTop) + setScrollTop(rightElem, scrollTop) + } else if (rightElem && fixedType === 'right') { + setScrollTop(bodyElem, scrollTop) + setScrollTop(leftElem, scrollTop) + } else { + setScrollTop(leftElem, scrollTop) + setScrollTop(rightElem, scrollTop) } + $xeTable.handleScrollEvent(evnt, isRollY, isRollX, { + type: renderType, + fixed: fixedType, + scrollTop, + scrollLeft + }) } - // let isLoadScroll = false - if (scrollXLoad && isRollX) { - // isLoadScroll = true - $xeTable.triggerScrollXEvent(evnt) - } - if (scrollYLoad && isRollY) { - // isLoadScroll = true - $xeTable.triggerScrollYEvent(evnt) - } - - if (scrollLoadingTime !== null) { - clearTimeout(scrollLoadingTime) - } - // if (isLoadScroll) { - // tableReactData.scrollVMLoading = true - // scrollLoadingTime = setTimeout(() => { - // scrollLoadingTime = null - // tableReactData.scrollVMLoading = false - // }, 20) - // } else { - // tableReactData.scrollVMLoading = false - // } - - if (isRollX && validTip && validTip.reactData.visible) { - validTip.updatePlacement() + if (xHandleEl) { + xHandleEl.scrollLeft = scrollLeft + } else if (isRollX) { + tableInternalData.lastScrollTop = scrollTop + tableInternalData.lastScrollLeft = scrollLeft + setScrollLeft(headerElem, scrollLeft) + setScrollLeft(footerElem, scrollLeft) + $xeTable.handleScrollEvent(evnt, isRollY, isRollX, { + type: renderType, + fixed: fixedType, + scrollTop, + scrollLeft + }) } - $xeTable.dispatchEvent('scroll', { - type: renderType, - fixed: fixedType, - scrollTop, - scrollLeft, - scrollHeight: bodyElem.scrollHeight, - scrollWidth: bodyElem.scrollWidth, - bodyHeight, - bodyWidth, - isX: isRollX, - isY: isRollY - }, evnt) } let wheelTime: any @@ -745,7 +660,6 @@ export default defineComponent({ const { fixedType } = props const { elemStore } = tableInternalData const prefix = `${fixedType || 'main'}-body-` - const el = refElem.value elemStore[`${prefix}wrapper`] = refElem elemStore[`${prefix}table`] = refBodyTable elemStore[`${prefix}colgroup`] = refBodyColgroup @@ -753,20 +667,11 @@ export default defineComponent({ elemStore[`${prefix}xSpace`] = refBodyXSpace elemStore[`${prefix}ySpace`] = refBodyYSpace elemStore[`${prefix}emptyBlock`] = refBodyEmptyBlock - if (el) { - el.onscroll = scrollEvent - el._onscroll = scrollEvent - } }) }) onBeforeUnmount(() => { - const el = refElem.value clearTimeout(wheelTime) - if (el) { - el._onscroll = null - el.onscroll = null - } }) onUnmounted(() => { @@ -832,6 +737,7 @@ export default defineComponent({ ref: refElem, class: ['vxe-table--body-wrapper', fixedType ? `fixed-${fixedType}--wrapper` : 'body--wrapper'], xid: xID, + onScroll: scrollEvent, ...(sYOpts.mode === 'wheel' ? { onWheel: wheelEvent } : {}) }, [ fixedType diff --git a/packages/table/src/footer.ts b/packages/table/src/footer.ts index 30097d0fdd..cd2034c2ce 100644 --- a/packages/table/src/footer.ts +++ b/packages/table/src/footer.ts @@ -1,7 +1,7 @@ import { createCommentVNode, defineComponent, h, ref, Ref, PropType, inject, nextTick, onMounted, onUnmounted } from 'vue' import XEUtils from 'xe-utils' import { VxeUI } from '../../ui' -import { updateCellTitle, getPropClass } from '../../ui/src/dom' +import { updateCellTitle, getPropClass, setScrollLeft } from '../../ui/src/dom' import type { VxeTablePrivateMethods, VxeTableConstructor, VxeTableMethods, VxeColumnPropTypes, VxeTableDefines } from '../../../types' @@ -47,7 +47,7 @@ export default defineComponent({ const $xeTable = inject('$xeTable', {} as VxeTableConstructor & VxeTableMethods & VxeTablePrivateMethods) const { xID, props: tableProps, reactData: tableReactData, internalData: tableInternalData } = $xeTable - const { refTableHeader, refTableBody, refValidTooltip } = $xeTable.getRefMaps() + const { refTableHeader, refTableBody, refScrollXHandleElem } = $xeTable.getRefMaps() const { computeTooltipOpts, computeColumnOpts } = $xeTable.getComputeMaps() const refElem = ref() as Ref @@ -61,33 +61,32 @@ export default defineComponent({ * 如果存在列固定左侧,同步更新滚动状态 * 如果存在列固定右侧,同步更新滚动状态 */ - const scrollEvent = (evnt: MouseEvent) => { + const scrollEvent = (evnt: Event) => { const { fixedType } = props - const { scrollXLoad } = tableReactData - const { lastScrollLeft } = tableInternalData - const validTip = refValidTooltip.value const tableHeader = refTableHeader.value const tableBody = refTableBody.value const headerElem = tableHeader ? tableHeader.$el as HTMLDivElement : null const footerElem = refElem.value const bodyElem = tableBody.$el as HTMLDivElement const scrollLeft = footerElem.scrollLeft - const isX = scrollLeft !== lastScrollLeft - tableInternalData.lastScrollLeft = scrollLeft - tableReactData.lastScrollTime = Date.now() - if (headerElem) { - headerElem.scrollLeft = scrollLeft + const xHandleEl = refScrollXHandleElem.value + if (xHandleEl) { + xHandleEl.scrollLeft = scrollLeft + } else { + const isRollX = true + const isRollY = false + const scrollTop = bodyElem.scrollTop + tableInternalData.lastScrollLeft = scrollLeft + tableReactData.lastScrollTime = Date.now() + setScrollLeft(headerElem, scrollLeft) + setScrollLeft(bodyElem, scrollLeft) + $xeTable.handleScrollEvent(evnt, isRollY, isRollX, { + type: renderType, + fixed: fixedType, + scrollTop, + scrollLeft + }) } - if (bodyElem) { - bodyElem.scrollLeft = scrollLeft - } - if (scrollXLoad && isX) { - $xeTable.triggerScrollXEvent(evnt) - } - if (isX && validTip && validTip.reactData.visible) { - validTip.updatePlacement() - } - $xeTable.dispatchEvent('scroll', { type: renderType, fixed: fixedType, scrollTop: bodyElem.scrollTop, scrollLeft, isX, isY: false }, evnt) } onMounted(() => { diff --git a/packages/table/src/table.ts b/packages/table/src/table.ts index dd89b2e094..35f2018dc2 100644 --- a/packages/table/src/table.ts +++ b/packages/table/src/table.ts @@ -9,7 +9,7 @@ import TableHeaderComponent from './header' import TableFooterComponent from './footer' import tableProps from './props' import tableEmits from './emits' -import { getRowUniqueId, clearTableAllStatus, getRowkey, getRowid, rowToVisible, colToVisible, getCellValue, setCellValue, handleFieldOrColumn, toTreePathSeq, restoreScrollLocation, restoreScrollListener, XEBodyScrollElement, getRootColumn } from './util' +import { getRowUniqueId, clearTableAllStatus, getRowkey, getRowid, rowToVisible, colToVisible, getCellValue, setCellValue, handleFieldOrColumn, toTreePathSeq, restoreScrollLocation, XEBodyScrollElement, getRootColumn } from './util' import { getSlotVNs } from '../../ui/src/vn' import { warnLog, errLog } from '../../ui/src/log' import TableCustomPanelComponent from '../module/custom/panel' @@ -367,6 +367,13 @@ export default defineComponent({ const refCellResizeBar = ref() as Ref const refEmptyPlaceholder = ref() as Ref + const refScrollXVirtualElem = ref() + const refScrollYVirtualElem = ref() + const refScrollXHandleElem = ref() + const refScrollYHandleElem = ref() + const refScrollXSpaceElem = ref() + const refScrollYSpaceElem = ref() + const $xeGrid = inject<(VxeGridConstructor & VxeGridPrivateMethods) | null>('$xeGrid', null) let $xeToolbar: VxeToolbarConstructor @@ -618,6 +625,14 @@ export default defineComponent({ return false }) + const computeVirtualScrollBars = computed(() => { + const { overflowX, scrollXLoad, overflowY, scrollYLoad } = reactData + return { + x: overflowX && scrollXLoad, + y: overflowY && scrollYLoad + } + }) + const refMaps: VxeTablePrivateRef = { refElem, refTooltip, @@ -636,7 +651,13 @@ export default defineComponent({ refTableRightFooter, refLeftContainer, refRightContainer, - refCellResizeBar + refCellResizeBar, + refScrollXVirtualElem, + refScrollYVirtualElem, + refScrollXHandleElem, + refScrollYHandleElem, + refScrollXSpaceElem, + refScrollYSpaceElem } const computeMaps: VxeTablePrivateComputed = { @@ -676,7 +697,8 @@ export default defineComponent({ computeCustomOpts, computeFixedColumnSize, computeIsMaxFixedColumn, - computeIsAllCheckboxDisabled + computeIsAllCheckboxDisabled, + computeVirtualScrollBars } const $xeTable = { @@ -748,7 +770,7 @@ export default defineComponent({ return reserveList } - const computeVirtualX = () => { + const handleVirtualXVisible = () => { const { visibleColumn } = internalData const tableBody = refTableBody.value const tableBodyElem = tableBody ? tableBody.$el as HTMLDivElement : null @@ -775,15 +797,15 @@ export default defineComponent({ return { toVisibleIndex: 0, visibleSize: 6 } } - const computeVirtualY = () => { + const computeRowHeight = () => { const tableHeader = refTableHeader.value const tableBody = refTableBody.value const tableBodyElem = tableBody ? tableBody.$el as HTMLDivElement : null const vSize = computeSize.value const rowHeightMaps = computeRowHeightMaps.value + let rowHeight = 0 if (tableBodyElem) { const tableHeaderElem = tableHeader ? tableHeader.$el as HTMLDivElement : null - let rowHeight = 0 let firstTrElem firstTrElem = tableBodyElem.querySelector('tr') if (!firstTrElem && tableHeaderElem) { @@ -795,10 +817,42 @@ export default defineComponent({ if (!rowHeight) { rowHeight = rowHeightMaps[vSize || 'default'] } - const visibleSize = Math.max(8, Math.ceil(tableBodyElem.clientHeight / rowHeight) + 2) - return { rowHeight, visibleSize } } - return { rowHeight: 0, visibleSize: 8 } + return rowHeight + } + + const handleVirtualYVisible = () => { + const { scrollYStore, afterFullData, fullAllDataRowIdData } = internalData + const tableBody = refTableBody.value + const tableBodyElem = tableBody ? tableBody.$el as HTMLDivElement : null + const { rowHeight } = scrollYStore + if (tableBodyElem) { + const { scrollTop, clientHeight } = tableBodyElem + const endHeight = scrollTop + clientHeight + let toVisibleIndex = -1 + let offsetTop = 0 + let visibleSize = 0 + for (let rIndex = 0, rLen = afterFullData.length; rIndex < rLen; rIndex++) { + const row = afterFullData[rIndex] + const rowid = getRowid($xeTable, row) + const rowRest = fullAllDataRowIdData[rowid] + if (!rowRest) { + break + } + offsetTop += rowRest.height || rowHeight + if (toVisibleIndex === -1 && scrollTop < offsetTop) { + toVisibleIndex = rIndex + } + if (toVisibleIndex >= 0) { + visibleSize++ + if (offsetTop > endHeight) { + break + } + } + } + return { toVisibleIndex: Math.max(0, toVisibleIndex), visibleSize: Math.max(8, visibleSize) } + } + return { toVisibleIndex: 0, visibleSize: 8 } } const calculateMergerOffsetIndex = (list: any[], offsetItem: any, type: 'row' | 'col') => { @@ -905,7 +959,7 @@ export default defineComponent({ }) } - const calcHeight = (key: 'height' | 'minHeight' | 'maxHeight') => { + const calcTableHeight = (key: 'height' | 'minHeight' | 'maxHeight') => { const { parentHeight } = reactData const val = props[key] let num = 0 @@ -1000,8 +1054,8 @@ export default defineComponent({ */ const cacheColumnMap = () => { const { tableFullColumn, collectColumn } = internalData - const fullColumnIdData: any = internalData.fullColumnIdData = {} - const fullColumnFieldData: any = internalData.fullColumnFieldData = {} + const fullColumnIdData: Record = internalData.fullColumnIdData = {} + const fullColumnFieldData: Record = internalData.fullColumnFieldData = {} const mouseOpts = computeMouseOpts.value const columnOpts = computeColumnOpts.value const rowOpts = computeRowOpts.value @@ -1015,7 +1069,7 @@ export default defineComponent({ let hasFixed: VxeColumnPropTypes.Fixed | undefined const handleFunc = (column: VxeTableDefines.ColumnInfo, index: number, items: VxeTableDefines.ColumnInfo[], path?: string[], parent?: VxeTableDefines.ColumnInfo) => { const { id: colid, field, fixed, type, treeNode } = column - const rest = { column, colid, index, items, parent } + const rest = { $index: -1, _index: -1, column, colid, index, items, parent: parent || null, width: 0 } if (field) { if (process.env.VUE_APP_VXE_ENV === 'development') { if (fullColumnFieldData[field]) { @@ -1107,9 +1161,9 @@ export default defineComponent({ } const updateHeight = () => { - internalData.customHeight = calcHeight('height') - internalData.customMinHeight = calcHeight('minHeight') - internalData.customMaxHeight = calcHeight('maxHeight') + internalData.customHeight = calcTableHeight('height') + internalData.customMinHeight = calcTableHeight('minHeight') + internalData.customMaxHeight = calcTableHeight('maxHeight') } const calcCellWidth = () => { @@ -1121,9 +1175,12 @@ export default defineComponent({ } reactData.isCalcColumn = true return nextTick().then(() => { + const { fullColumnIdData } = internalData const el = refElem.value if (el) { autoWidthColumnList.forEach(column => { + const colid = column.id + const colRest = fullColumnIdData[colid] const cellElList = el.querySelectorAll(`.vxe-header--column.${column.id}>.vxe-cell,.vxe-body--column.${column.id}>.vxe-cell,.vxe-footer--column.${column.id}>.vxe-cell`) const firstCellEl = cellElList[0] let paddingSize = 0 @@ -1150,6 +1207,9 @@ export default defineComponent({ colWidth = Math.max(colWidth, Math.ceil(titleWidth) + 4) } }) + if (colRest) { + colRest.width = Math.max(colWidth, colRest.width) + } column.renderAutoWidth = colWidth + paddingSize }) tablePrivateMethods.analyColumnWidth() @@ -1302,6 +1362,27 @@ export default defineComponent({ } } + const calcCellHeight = () => { + const { tableData, scrollYLoad } = reactData + const { fullAllDataRowIdData } = internalData + const el = refElem.value + if (scrollYLoad && el) { + tableData.forEach(row => { + const rowid = getRowid($xeTable, row) + const rowRest = fullAllDataRowIdData[rowid] + const trList = el.querySelectorAll(`.vxe-body--row[rowid="${rowid}"]`) + if (rowRest && trList.length) { + let height = 0 + for (let i = 0; i < trList.length; i++) { + const trEl = trList[i] as HTMLTableRowElement + height = Math.max(height, trEl.offsetHeight) + } + rowRest.height = height + } + }) + } + } + const getOrderField = (column: VxeTableDefines.ColumnInfo) => { const { sortBy, sortType } = column return (row: any) => { @@ -1336,13 +1417,13 @@ export default defineComponent({ if (treeConfig) { XEUtils.eachTree(afterTreeFullData, (row, index, items, path) => { const rowid = getRowid($xeTable, row) - const allrest = fullAllDataRowIdData[rowid] + const rowRest = fullAllDataRowIdData[rowid] const seq = path.map((num, i) => i % 2 === 0 ? (Number(num) + 1) : '.').join('') - if (allrest) { - allrest.seq = seq - allrest._index = index + if (rowRest) { + rowRest.seq = seq + rowRest._index = index } else { - const rest = { row, rowid, seq, index: -1, $index: -1, _index: index, items: [], parent: null, level: 0 } + const rest = { row, rowid, seq, index: -1, $index: -1, _index: index, items: [], parent: null, level: 0, height: 0 } fullAllDataRowIdData[rowid] = rest fullDataRowIdData[rowid] = rest } @@ -1351,13 +1432,13 @@ export default defineComponent({ } else { afterFullData.forEach((row, index) => { const rowid = getRowid($xeTable, row) - const allrest = fullAllDataRowIdData[rowid] + const rowRest = fullAllDataRowIdData[rowid] const seq = index + 1 - if (allrest) { - allrest.seq = seq - allrest._index = index + if (rowRest) { + rowRest.seq = seq + rowRest._index = index } else { - const rest = { row, rowid, seq, index: -1, $index: -1, _index: index, items: [], parent: null, level: 0 } + const rest = { row, rowid, seq, index: -1, $index: -1, _index: index, items: [], parent: null, level: 0, height: 0 } fullAllDataRowIdData[rowid] = rest fullDataRowIdData[rowid] = rest } @@ -1539,7 +1620,7 @@ export default defineComponent({ const updateStyle = () => { const { border, showFooter, 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 + const { isGroup, currentRow, tableColumn, scrollXLoad, scrollYLoad, overflowX, 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'] const emptyPlaceholderElem = refEmptyPlaceholder.value @@ -1557,6 +1638,33 @@ export default defineComponent({ customHeight += scrollbarHeight } } + + const scrollXVirtualEl = refScrollXVirtualElem.value + if (scrollXVirtualEl) { + scrollXVirtualEl.style.height = `${scrollbarHeight}px` + } + + const scrollYVirtualEl = refScrollYVirtualElem.value + if (scrollYVirtualEl) { + let bodyHeight = 0 + let bodyMaxHeight = 0 + const bodyMinHeight = customMinHeight - headerHeight - footerHeight + if (customMaxHeight) { + bodyMaxHeight = customMaxHeight - headerHeight - footerHeight + bodyMaxHeight = Math.max(bodyMinHeight, bodyMaxHeight) + } + if (customHeight) { + bodyHeight = customHeight - headerHeight - footerHeight + if (bodyMaxHeight) { + bodyHeight = Math.min(bodyMaxHeight, bodyHeight) + } + bodyHeight = Math.max(bodyMinHeight, bodyHeight) + } + scrollYVirtualEl.style.top = `${headerHeight}px` + scrollYVirtualEl.style.width = `${scrollbarWidth}px` + scrollYVirtualEl.style.height = `${bodyHeight + (overflowX ? -Math.max(1, scrollbarHeight) : 0)}px` + } + containerList.forEach((name, index) => { const fixedType = index > 0 ? name : '' const layoutList = ['header', 'body', 'footer'] @@ -1733,7 +1841,8 @@ export default defineComponent({ colElem.style.width = `${scrollbarWidth}px` } if (fullColumnIdData[colid]) { - const column = fullColumnIdData[colid].column + const colRest = fullColumnIdData[colid] + const column = colRest.column const { showHeaderOverflow, showFooterOverflow, showOverflow } = column let cellOverflow colElem.style.width = `${column.renderWidth}px` @@ -2140,12 +2249,12 @@ export default defineComponent({ const { treeExpandLazyLoadedMaps } = reactData const { fullAllDataRowIdData } = internalData const rowid = getRowid($xeTable, row) - const rest = fullAllDataRowIdData[rowid] + const rowRest = fullAllDataRowIdData[rowid] treeExpandLazyLoadedMaps[rowid] = row Promise.resolve( loadMethod({ $table: $xeTable, row }) ).then((childRecords: any) => { - rest.treeLoaded = true + rowRest.treeLoaded = true if (treeExpandLazyLoadedMaps[rowid]) { delete treeExpandLazyLoadedMaps[rowid] } @@ -2171,7 +2280,7 @@ export default defineComponent({ } }).catch(() => { const { treeExpandLazyLoadedMaps } = reactData - rest.treeLoaded = false + rowRest.treeLoaded = false if (treeExpandLazyLoadedMaps[rowid]) { delete treeExpandLazyLoadedMaps[rowid] } @@ -2205,14 +2314,14 @@ export default defineComponent({ const { fullAllDataRowIdData } = internalData const { rowExpandLazyLoadedMaps } = reactData const rowid = getRowid($xeTable, row) - const rest = fullAllDataRowIdData[rowid] + const rowRest = fullAllDataRowIdData[rowid] rowExpandLazyLoadedMaps[rowid] = row loadMethod({ $table: $xeTable, row, rowIndex: tableMethods.getRowIndex(row), $rowIndex: tableMethods.getVMRowIndex(row) }).then(() => { const { rowExpandedMaps } = reactData - rest.expandLoaded = true + rowRest.expandLoaded = true rowExpandedMaps[rowid] = row }).catch(() => { - rest.expandLoaded = false + rowRest.expandLoaded = false }).finally(() => { const { rowExpandLazyLoadedMaps } = reactData if (rowExpandLazyLoadedMaps[rowid]) { @@ -2262,7 +2371,7 @@ export default defineComponent({ const sXOpts = computeSXOpts.value // 计算 X 逻辑 if (scrollXLoad) { - const { visibleSize: visibleXSize } = computeVirtualX() + const { visibleSize: visibleXSize } = handleVirtualYVisible() const offsetXSize = sXOpts.oSize ? XEUtils.toNumber(sXOpts.oSize) : (browse.edge ? 5 : 0) scrollXStore.offsetSize = offsetXSize scrollXStore.visibleSize = visibleXSize @@ -2271,9 +2380,12 @@ export default defineComponent({ } else { tablePrivateMethods.updateScrollXSpace() } + calcCellHeight() // 计算 Y 逻辑 - const { rowHeight, visibleSize: visibleYSize } = computeVirtualY() + const rowHeight = computeRowHeight() scrollYStore.rowHeight = rowHeight + reactData.rowHeight = rowHeight + const { visibleSize: visibleYSize } = handleVirtualYVisible() if (scrollYLoad) { const offsetYSize = sYOpts.oSize ? XEUtils.toNumber(sYOpts.oSize) : (browse.edge ? 10 : 0) scrollYStore.offsetSize = offsetYSize @@ -2283,7 +2395,6 @@ export default defineComponent({ } else { tablePrivateMethods.updateScrollYSpace() } - reactData.rowHeight = rowHeight nextTick(updateStyle) }) } @@ -2361,9 +2472,9 @@ export default defineComponent({ if (!(props.height || props.maxHeight)) { errLog('vxe.error.reqProp', ['table.height | table.max-height | table.scroll-y={enabled: false}']) } - if (!props.showOverflow) { - warnLog('vxe.error.reqProp', ['table.show-overflow']) - } + // if (!props.showOverflow) { + // warnLog('vxe.error.reqProp', ['table.show-overflow']) + // } if (props.spanMethod) { warnLog('vxe.error.scrollErrProp', ['table.span-method']) } @@ -2443,9 +2554,9 @@ export default defineComponent({ const tableColumn = scrollXLoad ? visibleColumn.slice(scrollXStore.startIndex, scrollXStore.endIndex) : visibleColumn.slice(0) tableColumn.forEach((column, $index) => { const colid = column.id - const rest = fullColumnIdData[colid] - if (rest) { - rest.$index = $index + const colRest = fullColumnIdData[colid] + if (colRest) { + colRest.$index = $index } }) reactData.tableColumn = tableColumn @@ -2455,7 +2566,7 @@ export default defineComponent({ const { mergeList, mergeFooterList } = reactData const { scrollXStore } = internalData const { startIndex, endIndex, offsetSize } = scrollXStore - const { toVisibleIndex, visibleSize } = computeVirtualX() + const { toVisibleIndex, visibleSize } = handleVirtualXVisible() const offsetItem = { startIndex: Math.max(0, toVisibleIndex - 1 - offsetSize), endIndex: toVisibleIndex + visibleSize + offsetSize @@ -2560,7 +2671,7 @@ export default defineComponent({ warnLog('vxe.error.scrollErrProp', ['footer-span-method']) } } - const { visibleSize } = computeVirtualX() + const { visibleSize } = handleVirtualXVisible() scrollXStore.startIndex = 0 scrollXStore.endIndex = visibleSize scrollXStore.visibleSize = visibleSize @@ -2574,9 +2685,9 @@ export default defineComponent({ reactData.scrollXLoad = scrollXLoad visibleColumn.forEach((column, index) => { const colid = column.id - const rest = fullColumnIdData[colid] - if (rest) { - rest._index = index + const colRest = fullColumnIdData[colid] + if (colRest) { + colRest._index = index } }) internalData.visibleColumn = visibleColumn @@ -2678,8 +2789,8 @@ export default defineComponent({ validRows.forEach((row: any) => { const rowid = getRowid($xeTable, row) if (!treeTempExpandedMaps[rowid]) { - const rest = fullAllDataRowIdData[rowid] - const isLoad = lazy && row[hasChildField] && !rest.treeLoaded && !treeExpandLazyLoadedMaps[rowid] + const rowRest = fullAllDataRowIdData[rowid] + const isLoad = lazy && row[hasChildField] && !rowRest.treeLoaded && !treeExpandLazyLoadedMaps[rowid] // 是否使用懒加载 if (isLoad) { result.push(handleAsyncTreeExpandChilds(row)) @@ -2737,13 +2848,11 @@ export default defineComponent({ /** * 纵向 Y 可视渲染处理 */ - const loadScrollYData = (evnt: Event) => { + const loadScrollYData = () => { const { mergeList } = reactData const { scrollYStore } = internalData - const { startIndex, endIndex, visibleSize, offsetSize, rowHeight } = scrollYStore - const scrollBodyElem = (evnt.currentTarget || evnt.target) as HTMLDivElement - const scrollTop = scrollBodyElem.scrollTop - const toVisibleIndex = Math.floor(scrollTop / rowHeight) + const { startIndex, endIndex, offsetSize } = scrollYStore + const { toVisibleIndex, visibleSize } = handleVirtualYVisible() const offsetItem = { startIndex: Math.max(0, toVisibleIndex - 1 - offsetSize), endIndex: toVisibleIndex + visibleSize + offsetSize @@ -2764,9 +2873,9 @@ export default defineComponent({ const { fullAllDataRowIdData } = internalData if (row) { const rowid = getRowid($xeTable, row) - const rest = fullAllDataRowIdData[rowid] - if (rest) { - return rest[prop] + const rowRest = fullAllDataRowIdData[rowid] + if (rowRest) { + return rowRest[prop] } } return -1 @@ -2777,19 +2886,73 @@ export default defineComponent({ return function (column: VxeTableDefines.ColumnInfo) { const { fullColumnIdData } = internalData if (column) { - const rest = fullColumnIdData[column.id] - if (rest) { - return rest[prop] + const colRest = fullColumnIdData[column.id] + if (colRest) { + return colRest[prop] } } return -1 } } - const debounceScrollY = XEUtils.debounce(function (evnt: Event) { - loadScrollYData(evnt) + const debounceScrollYData = XEUtils.debounce(function () { + loadScrollYData() }, 20, { leading: false, trailing: true }) + const scrollXEvent = (evnt: Event) => { + const wrapperEl = evnt.currentTarget as HTMLDivElement + const tableHeader = refTableHeader.value + const tableBody = refTableBody.value + const tableFooter = refTableFooter.value + const bodyElem = tableBody.$el as HTMLDivElement + const headerElem = tableHeader ? tableHeader.$el as HTMLDivElement : null + const footerElem = tableFooter ? tableFooter.$el as HTMLDivElement : null + const { scrollTop, scrollLeft } = wrapperEl + const isRollX = true + const isRollY = false + internalData.lastScrollLeft = scrollLeft + reactData.lastScrollTime = Date.now() + setScrollLeft(bodyElem, scrollLeft) + setScrollLeft(headerElem, scrollLeft) + setScrollLeft(footerElem, scrollLeft) + $xeTable.triggerScrollXEvent(evnt) + $xeTable.handleScrollEvent(evnt, isRollY, isRollX, { + type: 'table', + fixed: '', + scrollTop, + scrollLeft + }) + } + + const debounceScrollYCalculate = XEUtils.debounce(function () { + tablePrivateMethods.updateScrollYSpace() + }, 1000, { leading: false, trailing: true }) + + const scrollYEvent = (evnt: Event) => { + const wrapperEl = evnt.currentTarget as HTMLDivElement + const tableBody = refTableBody.value + const leftBody = refTableLeftBody.value + const rightBody = refTableRightBody.value + const bodyElem = tableBody.$el as HTMLDivElement + const leftElem = leftBody ? leftBody.$el as HTMLDivElement : null + const rightElem = rightBody ? rightBody.$el as HTMLDivElement : null + const { scrollTop, scrollLeft } = wrapperEl + const isRollX = false + const isRollY = true + internalData.lastScrollTop = scrollTop + reactData.lastScrollTime = Date.now() + setScrollTop(bodyElem, scrollTop) + setScrollTop(leftElem, scrollTop) + setScrollTop(rightElem, scrollTop) + $xeTable.triggerScrollYEvent(evnt) + $xeTable.handleScrollEvent(evnt, isRollY, isRollX, { + type: 'table', + fixed: '', + scrollTop, + scrollLeft + }) + } + let keyCtxTimeout: any tableMethods = { @@ -2961,7 +3124,7 @@ export default defineComponent({ XEUtils.eachTree(rows, (childRow, index, items, path, parent, nodes) => { const rowid = getRowid($xeTable, childRow) const parentRow = parent || parentRest.row - const rest = { row: childRow, rowid, seq: -1, index, _index: -1, $index: -1, items, parent: parentRow, level: parentLevel + nodes.length } + const rest = { row: childRow, rowid, seq: -1, index, _index: -1, $index: -1, items, parent: parentRow, level: parentLevel + nodes.length, height: 0 } fullDataRowIdData[rowid] = rest fullAllDataRowIdData[rowid] = rest }, { children: childrenField }) @@ -3001,9 +3164,15 @@ export default defineComponent({ const { fullAllDataRowIdData } = internalData const rowid = tr.getAttribute('rowid') if (rowid) { - const rest = fullAllDataRowIdData[rowid] - if (rest) { - return { rowid: rest.rowid, item: rest.row, index: rest.index, items: rest.items, parent: rest.parent } + const rowRest = fullAllDataRowIdData[rowid] + if (rowRest) { + return { + rowid: rowRest.rowid, + item: rowRest.row, + index: rowRest.index, + items: rowRest.items, + parent: rowRest.parent + } } } } @@ -3018,9 +3187,15 @@ export default defineComponent({ const { fullColumnIdData } = internalData const colid = cell.getAttribute('colid') if (colid) { - const rest = fullColumnIdData[colid] - if (rest) { - return { colid: rest.colid, item: rest.column, index: rest.index, items: rest.items, parent: rest.parent } + const colRest = fullColumnIdData[colid] + if (colRest) { + return { + colid: colRest.colid, + item: colRest.column, + index: colRest.index, + items: colRest.items, + parent: colRest.parent + } } } } @@ -3200,13 +3375,13 @@ export default defineComponent({ const { fullAllDataRowIdData } = internalData const rowid = getRowid($xeTable, row) const colid = column.id - const rest = fullAllDataRowIdData[rowid] - if (rest) { - formatData = rest.formatData + const rowRest = fullAllDataRowIdData[rowid] + if (rowRest) { + formatData = rowRest.formatData if (!formatData) { formatData = fullAllDataRowIdData[rowid].formatData = {} } - if (rest && formatData[colid]) { + if (rowRest && formatData[colid]) { if (formatData[colid].value === cellValue) { return formatData[colid].label } @@ -3596,11 +3771,13 @@ export default defineComponent({ if (!el || !el.clientWidth) { return nextTick() } + calcCellHeight() calcCellWidth() autoCellWidth() if (reFull === true) { // 初始化时需要在列计算之后再执行优化运算,达到最优显示效果 return computeScrollLoad().then(() => { + calcCellHeight() autoCellWidth() return computeScrollLoad() }) @@ -4128,8 +4305,8 @@ export default defineComponent({ */ isRowExpandLoaded (row) { const { fullAllDataRowIdData } = internalData - const rest = fullAllDataRowIdData[getRowid($xeTable, row)] - return rest && !!rest.expandLoaded + const rowRest = fullAllDataRowIdData[getRowid($xeTable, row)] + return rowRest && !!rowRest.expandLoaded }, clearRowExpandLoaded (row) { const { rowExpandLazyLoadedMaps } = reactData @@ -4137,9 +4314,9 @@ export default defineComponent({ const expandOpts = computeExpandOpts.value const { lazy } = expandOpts const rowid = getRowid($xeTable, row) - const rest = fullAllDataRowIdData[rowid] - if (lazy && rest) { - rest.expandLoaded = false + const rowRest = fullAllDataRowIdData[rowid] + if (lazy && rowRest) { + rowRest.expandLoaded = false delete rowExpandLazyLoadedMaps[rowid] } return nextTick() @@ -4220,8 +4397,8 @@ export default defineComponent({ validRows.forEach((row: any) => { const rowid = getRowid($xeTable, row) if (!rExpandedMaps[rowid]) { - const rest = fullAllDataRowIdData[rowid] - const isLoad = lazy && !rest.expandLoaded && !rowExpandLazyLoadedMaps[rowid] + const rowRest = fullAllDataRowIdData[rowid] + const isLoad = lazy && !rowRest.expandLoaded && !rowExpandLazyLoadedMaps[rowid] if (isLoad) { lazyRests.push(handleAsyncRowExpand(row)) } else { @@ -4306,8 +4483,8 @@ export default defineComponent({ */ isTreeExpandLoaded (row) { const { fullAllDataRowIdData } = internalData - const rest = fullAllDataRowIdData[getRowid($xeTable, row)] - return rest && !!rest.treeLoaded + const rowRest = fullAllDataRowIdData[getRowid($xeTable, row)] + return rowRest && !!rowRest.treeLoaded }, clearTreeExpandLoaded (row) { const { treeExpandedMaps } = reactData @@ -4315,9 +4492,9 @@ export default defineComponent({ const treeOpts = computeTreeOpts.value const { transform, lazy } = treeOpts const rowid = getRowid($xeTable, row) - const rest = fullAllDataRowIdData[rowid] - if (lazy && rest) { - rest.treeLoaded = false + const rowRest = fullAllDataRowIdData[rowid] + if (lazy && rowRest) { + rowRest.treeLoaded = false if (treeExpandedMaps[rowid]) { delete treeExpandedMaps[rowid] } @@ -4528,28 +4705,44 @@ export default defineComponent({ clearScroll () { const { scrollXStore, scrollYStore } = internalData const tableBody = refTableBody.value + const tableHeader = refTableHeader.value const tableFooter = refTableFooter.value + const leftBody = refTableLeftBody.value const rightBody = refTableRightBody.value + const leftBodyElem = leftBody ? leftBody.$el as HTMLDivElement : null const tableBodyElem = tableBody ? tableBody.$el as XEBodyScrollElement : null const rightBodyElem = rightBody ? rightBody.$el as XEBodyScrollElement : null + const tableHeaderElem = tableHeader ? tableHeader.$el as HTMLDivElement : null const tableFooterElem = tableFooter ? tableFooter.$el as HTMLDivElement : null - if (rightBodyElem) { - restoreScrollListener(rightBodyElem) - rightBodyElem.scrollTop = 0 - } - if (tableFooterElem) { - tableFooterElem.scrollLeft = 0 + const xHandleEl = refScrollXHandleElem.value + if (xHandleEl) { + setScrollLeft(xHandleEl, 0) + } else { + setScrollLeft(tableBodyElem, 0) + setScrollLeft(tableHeaderElem, 0) + setScrollLeft(tableFooterElem, 0) } - if (tableBodyElem) { - restoreScrollListener(tableBodyElem) - tableBodyElem.scrollTop = 0 - tableBodyElem.scrollLeft = 0 + const yHandleEl = refScrollYHandleElem.value + if (yHandleEl) { + setScrollTop(yHandleEl, 0) + } else { + setScrollTop(tableBodyElem, 0) + setScrollTop(leftBodyElem, 0) + setScrollTop(rightBodyElem, 0) } scrollXStore.startIndex = 0 scrollXStore.endIndex = scrollXStore.visibleSize scrollYStore.startIndex = 0 scrollYStore.endIndex = scrollYStore.visibleSize - return nextTick() + return nextTick().then(() => { + setScrollLeft(tableBodyElem, 0) + setScrollLeft(tableHeaderElem, 0) + setScrollLeft(tableFooterElem, 0) + + setScrollTop(tableBodyElem, 0) + setScrollTop(leftBodyElem, 0) + setScrollTop(rightBodyElem, 0) + }) }, /** * 更新表尾合计 @@ -5485,7 +5678,7 @@ export default defineComponent({ } let cacheItem = fullAllDataRowIdData[rowid] if (!cacheItem) { - cacheItem = { row, rowid, seq, index: -1, _index: -1, $index: -1, items, parent, level } + cacheItem = { row, rowid, seq, index: -1, _index: -1, $index: -1, items, parent, level, height: 0 } } if (isSource) { cacheItem.index = treeConfig && parent ? -1 : index @@ -6363,18 +6556,52 @@ export default defineComponent({ triggerScrollXEvent () { loadScrollXData() }, + handleScrollEvent (evnt, isRollY, isRollX, params) { + const { highlightHoverRow } = props + const tableBody = refTableBody.value + const bodyElem = tableBody ? tableBody.$el as HTMLDivElement : null + const rowOpts = computeRowOpts.value + const validTip = refValidTooltip.value + const tooltip = refTooltip.value + if (rowOpts.isHover || highlightHoverRow) { + $xeTable.clearHoverRow() + } + if (validTip && validTip.reactData.visible) { + validTip.close() + } + if (tooltip && tooltip.reactData.visible) { + tooltip.close() + } + if (isRollX) { + tablePrivateMethods.checkScrolling() + } + const bodyHeight = bodyElem ? bodyElem.clientHeight : 0 + const bodyWidth = bodyElem ? bodyElem.clientWidth : 0 + const scrollHeight = bodyElem ? bodyElem.scrollHeight : 0 + const scrollWidth = bodyElem ? bodyElem.scrollWidth : 0 + $xeTable.dispatchEvent('scroll', { + bodyHeight, + bodyWidth, + scrollHeight, + scrollWidth, + isX: isRollX, + isY: isRollY, + ...params + }, evnt) + }, /** * 纵向 Y 可视渲染事件处理 */ - triggerScrollYEvent (evnt) { + triggerScrollYEvent () { const { scrollYStore } = internalData const { adaptive, offsetSize, visibleSize } = scrollYStore // webkit 浏览器使用最佳的渲染方式,且最高渲染量不能大于 40 条 if (isWebkit && adaptive && (offsetSize * 2 + visibleSize) <= 40) { - loadScrollYData(evnt) + loadScrollYData() } else { - debounceScrollY(evnt) + debounceScrollYData() } + debounceScrollYCalculate() }, /** * 对于树形结构中,可以直接滚动到指定深层节点中 @@ -6438,20 +6665,46 @@ export default defineComponent({ } }) }) + const scrollXSpaceEl = refScrollXSpaceElem.value + if (scrollXSpaceEl) { + scrollXSpaceEl.style.width = `${tableWidth + scrollbarWidth}px` + } nextTick(updateStyle) } }, // 更新纵向 Y 可视渲染上下剩余空间大小 updateScrollYSpace () { + const { showOverflow } = props const { scrollYLoad } = reactData - const { scrollYStore, elemStore, afterFullData } = internalData + const { scrollYStore, elemStore, afterFullData, fullAllDataRowIdData } = internalData const { startIndex, rowHeight } = scrollYStore - const bodyHeight = afterFullData.length * rowHeight - const topSpaceHeight = Math.max(0, startIndex * rowHeight) + let bodyHeight = 0 + let topSpaceHeight = 0 const containerList = ['main', 'left', 'right'] let marginTop = '' let ySpaceHeight = '' if (scrollYLoad) { + if (showOverflow) { + bodyHeight = afterFullData.length * rowHeight + topSpaceHeight = Math.max(0, startIndex * rowHeight) + } else { + for (let i = 0; i < afterFullData.length; i++) { + const row = afterFullData[i] + const rowid = getRowid($xeTable, row) + const rowRest = fullAllDataRowIdData[rowid] + if (rowRest) { + bodyHeight += rowRest.height || rowHeight + } + } + for (let i = 0; i < startIndex; i++) { + const row = afterFullData[i] + const rowid = getRowid($xeTable, row) + const rowRest = fullAllDataRowIdData[rowid] + if (rowRest) { + topSpaceHeight += rowRest.height || rowHeight + } + } + } marginTop = `${topSpaceHeight}px` ySpaceHeight = `${bodyHeight}px` } @@ -6470,6 +6723,10 @@ export default defineComponent({ } }) }) + const scrollYSpaceEl = refScrollYSpaceElem.value + if (scrollYSpaceEl) { + scrollYSpaceEl.style.height = ySpaceHeight + } nextTick(updateStyle) }, updateScrollXData () { @@ -6483,6 +6740,7 @@ export default defineComponent({ // reactData.tableData = [] nextTick(() => { tablePrivateMethods.handleTableData() + calcCellHeight() tablePrivateMethods.updateScrollYSpace() }) }, @@ -6494,16 +6752,18 @@ export default defineComponent({ const rightContainerElem = refRightContainer.value const tableBody = refTableBody.value const bodyElem = tableBody ? tableBody.$el as HTMLDivElement : null - if (bodyElem) { + const xHandleEl = refScrollXHandleElem.value + const bodtTargetEl = xHandleEl || bodyElem + if (bodtTargetEl) { if (leftContainerElem) { - if (bodyElem.scrollLeft > 0) { + if (bodtTargetEl.scrollLeft > 0) { addClass(leftContainerElem, 'scrolling--middle') } else { removeClass(leftContainerElem, 'scrolling--middle') } } if (rightContainerElem) { - if (bodyElem.clientWidth < bodyElem.scrollWidth - Math.ceil(bodyElem.scrollLeft)) { + if (bodtTargetEl.clientWidth < bodtTargetEl.scrollWidth - Math.ceil(bodtTargetEl.scrollLeft)) { addClass(rightContainerElem, 'scrolling--middle') } else { removeClass(rightContainerElem, 'scrolling--middle') @@ -6622,7 +6882,7 @@ export default defineComponent({ ]) } - const renderEmptyContenet = () => { + const renderEmptyBody = () => { const emptyOpts = computeEmptyOpts.value const params = { $table: $xeTable } if (slots.empty) { @@ -6662,6 +6922,7 @@ export default defineComponent({ const loadingOpts = computeLoadingOpts.value const isMenu = computeIsMenu.value const currLoading = reactData._isLoading || loading + const virtualScrollBars = computeVirtualScrollBars.value return h('div', { ref: refElem, class: ['vxe-table', 'vxe-table--render-default', `tid_${xID}`, `border--${tableBorder}`, { @@ -6703,6 +6964,7 @@ export default defineComponent({ class: 'vxe-table-slots' }, slots.default ? slots.default({}) : []), h('div', { + key: 'tw', class: 'vxe-table--render-wrapper' }, [ h('div', { @@ -6741,37 +7003,70 @@ export default defineComponent({ h('div', { class: 'vxe-table--fixed-wrapper' }, [ - /** - * 左侧固定区域 - */ leftList && leftList.length && overflowX ? renderFixed('left') : createCommentVNode(), - /** - * 右侧固定区域 - */ rightList && rightList.length && overflowX ? renderFixed('right') : createCommentVNode() ]) ]), + virtualScrollBars.x + ? h('div', { + key: 'vx', + ref: refScrollXVirtualElem, + class: 'vxe-table--scroll-x-virtual' + }, [ + h('div', { + ref: refScrollXHandleElem, + class: 'vxe-table--scroll-x-handle', + onScroll: scrollXEvent + }, [ + h('div', { + ref: refScrollXSpaceElem, + class: 'vxe-table--scroll-x-space' + }) + ]) + ]) + : createCommentVNode(), + virtualScrollBars.y + ? h('div', { + key: 'vy', + ref: refScrollYVirtualElem, + class: 'vxe-table--scroll-y-virtual' + }, [ + h('div', { + ref: refScrollYHandleElem, + class: 'vxe-table--scroll-y-handle', + onScroll: scrollYEvent + }, [ + h('div', { + ref: refScrollYSpaceElem, + class: 'vxe-table--scroll-x-space' + }) + ]) + ]) + : createCommentVNode(), /** * 空数据 */ h('div', { + key: 'tn', ref: refEmptyPlaceholder, class: 'vxe-table--empty-placeholder' }, [ h('div', { class: 'vxe-table--empty-content' - }, renderEmptyContenet()) + }, renderEmptyBody()) ]), /** * 边框线 */ h('div', { + key: 'tl', class: 'vxe-table--border-line' }), /** * 列宽线 */ h('div', { + key: 'cl', ref: refCellResizeBar, class: 'vxe-table--resizable-bar', style: overflowX @@ -6785,6 +7080,7 @@ export default defineComponent({ */ VxeUILoadingComponent ? h(VxeUILoadingComponent, { + key: 'lg', class: 'vxe-table--loading', modelValue: currLoading, icon: loadingOpts.icon, @@ -6800,6 +7096,7 @@ export default defineComponent({ */ initStore.custom ? h(TableCustomPanelComponent, { + key: 'cs', ref: refTableCustom, customStore }) @@ -6809,6 +7106,7 @@ export default defineComponent({ */ initStore.filter ? h(TableFilterPanelComponent, { + key: 'tf', ref: refTableFilter, filterStore }) @@ -6818,6 +7116,7 @@ export default defineComponent({ */ initStore.import && props.importConfig ? h(TableImportPanelComponent, { + key: 'it', defaultOptions: reactData.importParams, storeData: reactData.importStore }) @@ -6827,6 +7126,7 @@ export default defineComponent({ */ initStore.export && (props.exportConfig || props.printConfig) ? h(TableExportPanelComponent, { + key: 'et', defaultOptions: reactData.exportParams, storeData: reactData.exportStore }) @@ -6836,6 +7136,7 @@ export default defineComponent({ */ isMenu ? h(TableMenuPanelComponent, { + key: 'tm', ref: refTableMenu }) : createCommentVNode(), @@ -6848,6 +7149,7 @@ export default defineComponent({ * 通用提示 */ h(VxeUITooltipComponent, { + key: 'ctp', ref: refCommTooltip, isArrow: false, enterable: false @@ -6856,6 +7158,7 @@ export default defineComponent({ * 工具提示 */ h(VxeUITooltipComponent, Object.assign({ + key: 'btp', ref: refTooltip }, tipConfig, tooltipStore.currOpts)), /** @@ -6863,6 +7166,7 @@ export default defineComponent({ */ props.editRules && validOpts.showMessage && (validOpts.message === 'default' ? !height : validOpts.message === 'tooltip') ? h(VxeUITooltipComponent, { + key: 'vtp', ref: refValidTooltip, class: [{ 'old-cell-valid': editRules && getConfig().cellVaildMode === 'obsolete' diff --git a/packages/table/src/util.ts b/packages/table/src/util.ts index 2552cd0585..7f54904c82 100644 --- a/packages/table/src/util.ts +++ b/packages/table/src/util.ts @@ -85,17 +85,17 @@ export function restoreScrollLocation ($xeTable: VxeTableConstructor, scrollLeft }) } -export function removeScrollListener (scrollElem: XEBodyScrollElement | null) { - if (scrollElem && scrollElem._onscroll) { - scrollElem.onscroll = null - } -} - -export function restoreScrollListener (scrollElem: XEBodyScrollElement | null) { - if (scrollElem && scrollElem._onscroll) { - scrollElem.onscroll = scrollElem._onscroll - } -} +// export function removeScrollListener (scrollElem: XEBodyScrollElement | null) { +// if (scrollElem && scrollElem._onscroll) { +// scrollElem.onscroll = null +// } +// } + +// export function restoreScrollListener (scrollElem: XEBodyScrollElement | null) { +// if (scrollElem && scrollElem._onscroll) { +// scrollElem.onscroll = scrollElem._onscroll +// } +// } /** * 生成行的唯一主键 @@ -379,31 +379,59 @@ export function clearTableAllStatus ($xeTable: VxeTableConstructor & VxeTablePri export function rowToVisible ($xeTable: VxeTableConstructor & VxeTablePrivateMethods, row: any) { const { reactData, internalData } = $xeTable + const tableProps = $xeTable.props + const { showOverflow } = tableProps const { refTableBody } = $xeTable.getRefMaps() - const { scrollYLoad } = reactData - const { afterFullData, scrollYStore } = internalData + const { columnStore, scrollYLoad } = reactData + const { afterFullData, scrollYStore, fullAllDataRowIdData } = internalData const tableBody = refTableBody.value + const { leftList, rightList } = columnStore const bodyElem = tableBody ? tableBody.$el as HTMLDivElement : null + const rowid = getRowid($xeTable, row) + let offsetFixedLeft = 0 + leftList.forEach(item => { + offsetFixedLeft += item.renderWidth + }) + let offsetFixedRight = 0 + rightList.forEach(item => { + offsetFixedRight += item.renderWidth + }) if (bodyElem) { - const trElem: HTMLTableRowElement | null = bodyElem.querySelector(`[rowid="${getRowid($xeTable, row)}"]`) + const bodyHeight = bodyElem.clientHeight + const bodyScrollTop = bodyElem.scrollTop + const trElem: HTMLTableRowElement | null = bodyElem.querySelector(`[rowid="${rowid}"]`) if (trElem) { - const bodyHeight = bodyElem.clientHeight - const bodySrcollTop = bodyElem.scrollTop const trOffsetParent = trElem.offsetParent as HTMLElement const trOffsetTop = trElem.offsetTop + (trOffsetParent ? trOffsetParent.offsetTop : 0) const trHeight = trElem.clientHeight // 检测行是否在可视区中 - if (trOffsetTop < bodySrcollTop || trOffsetTop > bodySrcollTop + bodyHeight) { - // 向上定位 + if (trOffsetTop < bodyScrollTop || trOffsetTop > bodyScrollTop + bodyHeight) { return $xeTable.scrollTo(null, trOffsetTop) - } else if (trOffsetTop + trHeight >= bodyHeight + bodySrcollTop) { - // 向下定位 - return $xeTable.scrollTo(null, bodySrcollTop + trHeight) + } else if (trOffsetTop + trHeight >= bodyHeight + bodyScrollTop) { + return $xeTable.scrollTo(null, bodyScrollTop + trHeight) } } else { - // 如果是虚拟渲染跨行滚动 + // 如果是虚拟渲染滚动 if (scrollYLoad) { - return $xeTable.scrollTo(null, ($xeTable.findRowIndexOf(afterFullData, row) - 1) * scrollYStore.rowHeight) + if (showOverflow) { + return $xeTable.scrollTo(null, ($xeTable.findRowIndexOf(afterFullData, row) - 1) * scrollYStore.rowHeight) + } + let scrollTop = 0 + const rest = fullAllDataRowIdData[rowid] + const rHeight = rest ? rest.height : 0 + for (let i = 0; i < afterFullData.length; i++) { + const currRow = afterFullData[i] + const currRowid = getRowid($xeTable, currRow) + if (currRow === row || currRowid === rowid) { + break + } + const rest = fullAllDataRowIdData[currRowid] + scrollTop += rest ? rest.height : 0 + } + if (scrollTop < bodyScrollTop) { + return $xeTable.scrollTo(null, scrollTop - offsetFixedLeft - 1) + } + return $xeTable.scrollTo(null, (scrollTop + rHeight) - (bodyHeight - offsetFixedRight - 1)) } } } @@ -418,6 +446,9 @@ export function colToVisible ($xeTable: VxeTableConstructor & VxeTablePrivateMet const { leftList, rightList } = columnStore const tableBody = refTableBody.value const bodyElem = tableBody ? tableBody.$el as HTMLDivElement : null + if (column.fixed) { + return Promise.resolve() + } let offsetFixedLeft = 0 leftList.forEach(item => { offsetFixedLeft += item.renderWidth @@ -428,16 +459,16 @@ export function colToVisible ($xeTable: VxeTableConstructor & VxeTablePrivateMet }) if (bodyElem) { const bodyWidth = bodyElem.clientWidth - const bodySrcollLeft = bodyElem.scrollLeft + const bodyScrollLeft = bodyElem.scrollLeft const tdElem: HTMLTableCellElement | null = bodyElem.querySelector(`.${column.id}`) if (tdElem) { const tdOffsetParent = tdElem.offsetParent as HTMLElement const tdOffsetLeft = tdElem.offsetLeft + (tdOffsetParent ? tdOffsetParent.offsetLeft : 0) const cellWidth = tdElem.clientWidth // 检测是否在可视区中 - if (tdOffsetLeft < (bodySrcollLeft + offsetFixedLeft)) { + if (tdOffsetLeft < (bodyScrollLeft + offsetFixedLeft)) { return $xeTable.scrollTo(tdOffsetLeft - offsetFixedLeft - 1) - } else if ((tdOffsetLeft + cellWidth - bodySrcollLeft) > (bodyWidth - offsetFixedRight)) { + } else if ((tdOffsetLeft + cellWidth - bodyScrollLeft) > (bodyWidth - offsetFixedRight)) { return $xeTable.scrollTo((tdOffsetLeft + cellWidth) - (bodyWidth - offsetFixedRight - 1)) } } else { @@ -445,14 +476,14 @@ export function colToVisible ($xeTable: VxeTableConstructor & VxeTablePrivateMet if (scrollXLoad) { let scrollLeft = 0 const cellWidth = column.renderWidth - for (let index = 0; index < visibleColumn.length; index++) { - const currCol = visibleColumn[index] + for (let i = 0; i < visibleColumn.length; i++) { + const currCol = visibleColumn[i] if (currCol === column || currCol.id === column.id) { break } scrollLeft += currCol.renderWidth } - if (scrollLeft < bodySrcollLeft) { + if (scrollLeft < bodyScrollLeft) { return $xeTable.scrollTo(scrollLeft - offsetFixedLeft - 1) } return $xeTable.scrollTo((scrollLeft + cellWidth) - (bodyWidth - offsetFixedRight - 1)) diff --git a/packages/ui/index.ts b/packages/ui/index.ts index 4ae137043d..bee02f9354 100644 --- a/packages/ui/index.ts +++ b/packages/ui/index.ts @@ -6,7 +6,7 @@ import type { VxeUploadDefines, VxePrintDefines, VxeGlobalConfig } from 'vxe-pc- export const version = process.env.VUE_APP_VXE_VERSION as string VxeUI.version = version -VxeUI.tableVersion = process.env.VUE_APP_VXE_VERSION as string +VxeUI.tableVersion = version VxeUI.setConfig({ emptyCell: ' ', diff --git a/styles/components/table-module/filter.scss b/styles/components/table-module/filter.scss index 512cfed75c..9a2999ab52 100644 --- a/styles/components/table-module/filter.scss +++ b/styles/components/table-module/filter.scss @@ -36,7 +36,7 @@ border-radius: var(--vxe-ui-border-radius); background-color: var(--vxe-ui-layout-background-color); border: 1px solid var(--vxe-ui-base-popup-border-color); - box-shadow: 0 1px 6px rgba(0,0,0,.2); + box-shadow: var(--vxe-ui-base-popup-box-shadow); z-index: 10; &:not(.is--multiple) { text-align: center; diff --git a/styles/components/table.scss b/styles/components/table.scss index 7f4f3aea85..ca9bc5de5d 100644 --- a/styles/components/table.scss +++ b/styles/components/table.scss @@ -532,14 +532,10 @@ font-family: var(--vxe-ui-font-family); direction: ltr; .vxe-table--body-wrapper { - & > table { - background-color: var(--vxe-ui-layout-background-color); - } + background-color: var(--vxe-ui-layout-background-color); } .vxe-table--footer-wrapper { - & > table { - background-color: var(--vxe-ui-table-footer-background-color); - } + background-color: var(--vxe-ui-table-footer-background-color); } .vxe-table--header, .vxe-table--body, @@ -934,6 +930,48 @@ } } } + // 滚动条 + .vxe-table--scroll-x-virtual, + .vxe-table--scroll-y-virtual { + position: absolute; + z-index: 7; + overflow: hidden; + } + .vxe-table--scroll-x-handle, + .vxe-table--scroll-y-handle { + position: absolute; + div { + display: block; + } + } + .vxe-table--scroll-x-virtual, + .vxe-table--scroll-x-handle { + width: 100%; + left: 0; + bottom: 0; + } + .vxe-table--scroll-x-handle { + overflow-y: hidden; + overflow-x: auto; + height: 18px; + } + .vxe-table--scroll-y-virtual, + .vxe-table--scroll-y-handle { + height: 100%; + right: 0; + top: 0; + } + .vxe-table--scroll-y-handle { + overflow-y: auto; + overflow-x: hidden; + width: 18px; + } + .vxe-table--scroll-x-space { + height: 1px; + } + .vxe-table--scroll-y-space { + width: 1px; + } &.is--padding { .vxe-cell { @@ -972,6 +1010,7 @@ background-color: inherit; transition: 0.3s box-shadow; outline: 0; + background-color: var(--vxe-ui-layout-background-color); .vxe-table--body-wrapper { overflow-x: hidden; outline: 0; diff --git a/styles/modules.scss b/styles/modules.scss index a1eb5e57ea..5d979b29ff 100644 --- a/styles/modules.scss +++ b/styles/modules.scss @@ -1,5 +1,3 @@ -/*已废弃*/ - @use './components/column.scss'; @use './components/colgroup.scss'; @use './components/table.scss'; diff --git a/styles/theme/base.scss b/styles/theme/base.scss index b91074d543..08b859e687 100644 --- a/styles/theme/base.scss +++ b/styles/theme/base.scss @@ -68,7 +68,7 @@ --vxe-ui-table-cell-extend-area-border-color: var(--vxe-ui-table-cell-area-border-color); --vxe-ui-table-cell-active-area-border-color: var(--vxe-ui-table-cell-area-border-color); --vxe-ui-table-cell-area-background-color: rgba(64,158,255,0.2); - --vxe-ui-table-header-active-area-background-color: rgba(64,158,255,0.1); + --vxe-ui-table-header-active-area-background-color: rgba(64,158,255,0.05); --vxe-ui-table-expand-padding-default: 16px; diff --git a/styles/theme/dark.scss b/styles/theme/dark.scss index 0dce0e057c..0b50cf0d90 100644 --- a/styles/theme/dark.scss +++ b/styles/theme/dark.scss @@ -5,13 +5,16 @@ /*font color*/ --vxe-ui-font-color: #a0a3a7; + --vxe-ui-font-tinge-color: #33353b; + --vxe-ui-font-lighten-color: #797b80; + --vxe-ui-font-darken-color: #47494c; + --vxe-ui-font-disabled-color: #464646; + + /*font status color*/ --vxe-ui-font-primary-color: #409eff; - --vxe-ui-font-lighten-color: #babdc0; - --vxe-ui-font-darken-color: #86898e; - --vxe-ui-font-disabled-color: #BFBFBF; /*base*/ - --vxe-ui-base-popup-border-color: var(--vxe-ui-layout-background-color); + --vxe-ui-base-popup-border-color: #424242; --vxe-ui-base-popup-box-shadow: 0px 12px 30px 8px rgba(0, 0, 0, 0.5); /*layout*/ diff --git a/styles/variable.scss b/styles/variable.scss index 9a9519b2b7..3a617f6e96 100644 --- a/styles/variable.scss +++ b/styles/variable.scss @@ -1,36 +1,39 @@ /*font color*/ - $vxe-ui-font-color: #606266; - $vxe-ui-font-primary-color: #409eff; - $vxe-ui-font-lighten-color: #797b80; - $vxe-ui-font-darken-color: #47494c; - $vxe-ui-font-disabled-color: #BFBFBF; +$vxe-ui-font-color: #606266; +$vxe-ui-font-tinge-color: #d4d5d7; +$vxe-ui-font-lighten-color: #797b80; +$vxe-ui-font-darken-color: #47494c; +$vxe-ui-font-disabled-color: #BFBFBF; + +/*font status color*/ +$vxe-ui-font-primary-color: #409eff; /*base*/ - $vxe-ui-base-popup-border-color: #DADCE0; - $vxe-ui-base-popup-box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.16); +$vxe-ui-base-popup-border-color: #DADCE0; +$vxe-ui-base-popup-box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.16); /*layout*/ - $vxe-ui-layout-background-color: #ffffff; +$vxe-ui-layout-background-color: #ffffff; /*input*/ - $vxe-ui-input-border-color: #dcdfe6; - $vxe-ui-input-placeholder-color: #C0C4CC; - $vxe-ui-input-disabled-background-color: #f3f3f3; +$vxe-ui-input-border-color: #dcdfe6; +$vxe-ui-input-placeholder-color: #C0C4CC; +$vxe-ui-input-disabled-background-color: #f3f3f3; /*loading*/ - $vxe-ui-loading-background-color: rgba(255, 255, 255, 0.5); +$vxe-ui-loading-background-color: rgba(255, 255, 255, 0.5); /*table*/ - $vxe-ui-table-header-background-color: #f8f8f9; - $vxe-ui-table-border-color: #e8eaec; - $vxe-ui-table-row-hover-background-color: #f5f7fa; - $vxe-ui-table-row-striped-background-color: #fafafa; - $vxe-ui-table-row-hover-striped-background-color: #f5f7fa; - $vxe-ui-table-row-radio-checked-background-color: #fff3e0; - $vxe-ui-table-row-hover-radio-checked-background-color: #ffebbc; - $vxe-ui-table-row-checkbox-checked-background-color: #fff3e0; - $vxe-ui-table-row-hover-checkbox-checked-background-color: #ffebbc; - $vxe-ui-table-row-current-background-color: #e6f7ff; - $vxe-ui-table-row-hover-current-background-color: #d7effb; - $vxe-ui-table-fixed-scrolling-box-shadow-color: rgba(0, 0, 0, 0.12); +$vxe-ui-table-header-background-color: #f8f8f9; +$vxe-ui-table-border-color: #e8eaec; +$vxe-ui-table-row-hover-background-color: #f5f7fa; +$vxe-ui-table-row-striped-background-color: #fafafa; +$vxe-ui-table-row-hover-striped-background-color: #f5f7fa; +$vxe-ui-table-row-radio-checked-background-color: #fff3e0; +$vxe-ui-table-row-hover-radio-checked-background-color: #ffebbc; +$vxe-ui-table-row-checkbox-checked-background-color: #fff3e0; +$vxe-ui-table-row-hover-checkbox-checked-background-color: #ffebbc; +$vxe-ui-table-row-current-background-color: #e6f7ff; +$vxe-ui-table-row-hover-current-background-color: #d7effb; +$vxe-ui-table-fixed-scrolling-box-shadow-color: rgba(0, 0, 0, 0.12); \ No newline at end of file