UNPKG

wetrade-design

Version:

一款多语言支持Vue3的UI框架

1,078 lines 48.2 kB
import _defineProperty from "@babel/runtime/helpers/esm/defineProperty"; import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2"; import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray"; import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray"; import _typeof from "@babel/runtime/helpers/esm/typeof"; import { Fragment as _Fragment, createVNode as _createVNode, resolveDirective as _resolveDirective } from "vue"; import Header from './Header/Header'; import Body from './Body'; import useColumns from './hooks/useColumns'; import { useLayoutState, useTimeoutLock } from './hooks/useFrame'; import { getPathValue, mergeObject, validateValue, getColumnsKey } from './utils/valueUtil'; import useStickyOffsets from './hooks/useStickyOffsets'; import ColGroup from './ColGroup'; import Panel from './Panel'; import Footer from './Footer'; import { findAllChildrenKeys, renderExpandIcon } from './utils/expandUtil'; import { getCellFixedInfo } from './utils/fixUtil'; import StickyScrollBar from './stickyScrollBar'; import useSticky from './hooks/useSticky'; import FixedHolder from './FixedHolder'; import { onUpdated, computed, defineComponent, nextTick, onMounted, onBeforeUnmount, reactive, ref, shallowRef, toRef, toRefs, watch, watchEffect, provide, customRef } from 'vue'; import { warning } from '../vc-util/warning'; import { reactivePick } from '../_util/reactivePick'; import useState from '../_util/hooks/useState'; import { toPx } from '../_util/util'; import isVisible from '../vc-util/Dom/isVisible'; import { getTargetScrollBarSize } from '../_util/getScrollBarSize'; import getRequestAnimationFrame, { cancelRequestAnimationFrame } from '../_util/getRequestAnimationFrame'; import classNames from '../_util/classNames'; import VCResizeObserver from '../vc-resize-observer'; import { useProvideTable } from './context/TableContext'; import { useProvideBody } from './context/BodyContext'; import { useProvideResize, useProvideInitScroll, FullTableRefKey, HasDataKey, ResizeColumnStartRefKey, ResizeColumnMoveRefKey, ResizeColumnStatusKey } from './context/ResizeContext'; import { useProvideSticky } from './context/StickyContext'; import pickAttrs from '../_util/pickAttrs'; import { useProvideExpandedRow } from './context/ExpandedRowContext'; import ScrollBar from '../scrollbar'; import { INTERNAL_COL_DEFINE } from './utils/legacyUtil'; // Used for conditions cache var EMPTY_DATA = []; // Used for customize scroll var EMPTY_SCROLL_TARGET = {}; export var INTERNAL_HOOKS = 'rc-table-internal-hook'; export default defineComponent({ name: 'Table', inheritAttrs: false, props: ['prefixCls', 'data', 'columns', 'rowKey', 'tableLayout', 'scroll', 'rowClassName', 'title', 'footer', 'id', 'showHeader', 'components', 'customRow', 'customHeaderRow', 'direction', 'expandFixed', 'expandColumnWidth', 'expandedRowKeys', 'defaultExpandedRowKeys', 'expandedRowRender', 'expandRowByClick', 'expandIcon', 'onExpand', 'onExpandedRowsChange', 'onUpdate:expandedRowKeys', 'defaultExpandAllRows', 'indentSize', 'expandIconColumnIndex', 'expandedRowClassName', 'childrenColumnName', 'rowExpandable', 'sticky', 'transformColumns', 'internalHooks', 'internalRefs', 'canExpandable', 'onUpdateInternalRefs', 'transformCellText', 'isMaxHeight', 'isScrollPosition', 'virtualScroll'], slots: ['title', 'footer', 'summary', 'emptyText'], emits: ['expand', 'expandedRowsChange', 'updateInternalRefs', 'update:expandedRowKeys'], setup: function setup(props, _ref) { var attrs = _ref.attrs, slots = _ref.slots, emit = _ref.emit, expose = _ref.expose; var mergedData = computed(function () { return props.data || EMPTY_DATA; }); var hasData = computed(function () { return !!mergedData.value.length; }); // ==================== Customize ===================== var mergedComponents = computed(function () { return mergeObject(props.components, {}); }); var getComponent = function getComponent(path, defaultComponent) { return getPathValue(mergedComponents.value, path) || defaultComponent; }; var getRowKey = computed(function () { var rowKey = props.rowKey; if (typeof rowKey === 'function') { return rowKey; } return function (record) { var key = record && record[rowKey]; if (process.env.NODE_ENV !== 'production') { warning(key !== undefined, 'Each record in table should have a unique `key` prop, or set `rowKey` to an unique primary key.'); } return key; }; }); // ====================== Expand ====================== var mergedExpandIcon = computed(function () { return props.expandIcon || renderExpandIcon; }); var mergedChildrenColumnName = computed(function () { return props.childrenColumnName || 'children'; }); var expandableType = computed(function () { if (props.expandedRowRender) { return 'row'; } /* eslint-disable no-underscore-dangle */ /** * Fix https://github.com/ant-design/ant-design/issues/21154 * This is a workaround to not to break current behavior. * We can remove follow code after final release. * * To other developer: * Do not use `__PARENT_RENDER_ICON__` in prod since we will remove this when refactor */ if (props.canExpandable || mergedData.value.some(function (record) { return record && _typeof(record) === 'object' && record[mergedChildrenColumnName.value]; })) { return 'nest'; } /* eslint-enable */ return false; }); var innerExpandedKeys = shallowRef([]); var stop = watchEffect(function () { if (props.defaultExpandedRowKeys) { innerExpandedKeys.value = props.defaultExpandedRowKeys; } if (props.defaultExpandAllRows) { innerExpandedKeys.value = findAllChildrenKeys(mergedData.value, getRowKey.value, mergedChildrenColumnName.value); } }); // defalutXxxx 仅仅第一次生效 stop(); var mergedExpandedKeys = computed(function () { return new Set(props.expandedRowKeys || innerExpandedKeys.value || []); }); var onTriggerExpand = function onTriggerExpand(record) { var key = getRowKey.value(record, mergedData.value.indexOf(record)); var newExpandedKeys; var hasKey = mergedExpandedKeys.value.has(key); if (hasKey) { mergedExpandedKeys.value.delete(key); newExpandedKeys = _toConsumableArray(mergedExpandedKeys.value); } else { newExpandedKeys = [].concat(_toConsumableArray(mergedExpandedKeys.value), [key]); } innerExpandedKeys.value = newExpandedKeys; emit('expand', !hasKey, record); emit('update:expandedRowKeys', newExpandedKeys); emit('expandedRowsChange', newExpandedKeys); }; // Warning if use `expandedRowRender` and nest children in the same time if (process.env.NODE_ENV !== 'production' && props.expandedRowRender && mergedData.value.some(function (record) { return Array.isArray(record === null || record === void 0 ? void 0 : record[mergedChildrenColumnName.value]); })) { warning(false, '`expandedRowRender` should not use with nested Table'); } var componentWidth = ref(0); var _useColumns = useColumns(_objectSpread(_objectSpread({}, toRefs(props)), {}, { // children, expandable: computed(function () { return !!props.expandedRowRender; }), expandedKeys: mergedExpandedKeys, getRowKey: getRowKey, onTriggerExpand: onTriggerExpand, expandIcon: mergedExpandIcon }), computed(function () { return props.internalHooks === INTERNAL_HOOKS ? props.transformColumns : null; })), _useColumns2 = _slicedToArray(_useColumns, 2), columns = _useColumns2[0], flattenColumns = _useColumns2[1]; var columnContext = computed(function () { return { columns: columns.value, flattenColumns: flattenColumns.value }; }); // ====================== Scroll ====================== var fullTableRef = ref(); var scrollHeaderRef = ref(); var scrollBodyRef = ref(); var scrollBarRef = ref(); var resizeColumnMoveRef = ref(); var resizeColumnStartRef = ref(); var isResizingHandle = ref(false); var scrollBodySizeInfo = ref({ scrollWidth: 0, clientWidth: 0 }); var scrollSummaryRef = ref(); var _useState = useState(false), _useState2 = _slicedToArray(_useState, 2), pingedLeft = _useState2[0], setPingedLeft = _useState2[1]; var _useState3 = useState(false), _useState4 = _slicedToArray(_useState3, 2), pingedRight = _useState4[0], setPingedRight = _useState4[1]; var _useLayoutState = useLayoutState(new Map()), _useLayoutState2 = _slicedToArray(_useLayoutState, 2), colsWidths = _useLayoutState2[0], updateColsWidths = _useLayoutState2[1]; var layout = reactive({ scrollX: false, scrollY: false }); // 滚动的方向 var scrollDirection = reactive({ left: false, middle: false, right: false }); // Convert map to number width var colsKeys = computed(function () { return getColumnsKey(flattenColumns.value); }); var colWidths = computed(function () { return colsKeys.value.map(function (columnKey) { return colsWidths.value.get(columnKey); }); }); var columnCount = computed(function () { return flattenColumns.value.length; }); var stickyOffsets = useStickyOffsets(colWidths, columnCount, toRef(props, 'direction')); var fixHeader = computed(function () { return props.scroll && validateValue(props.scroll.y); }); var horizonScroll = computed(function () { return props.scroll && validateValue(props.scroll.x) || Boolean(props.expandFixed); }); var fixColumn = computed(function () { return horizonScroll.value && flattenColumns.value.some(function (_ref2) { var fixed = _ref2.fixed; return fixed; }); }); // Sticky var stickyRef = ref(); var stickyState = useSticky(toRef(props, 'sticky'), toRef(props, 'prefixCls')); var summaryFixedInfos = reactive({}); var fixFooter = computed(function () { var info = Object.values(summaryFixedInfos)[0]; return (fixHeader.value || stickyState.value.isSticky) && info; }); var summaryCollect = function summaryCollect(uniKey, fixed) { if (fixed) { summaryFixedInfos[uniKey] = fixed; } else { delete summaryFixedInfos[uniKey]; } }; // Scroll var scrollXStyle = ref({}); var scrollYStyle = ref({}); var scrollTableStyle = ref({}); watchEffect(function () { if (fixHeader.value) { scrollYStyle.value = { // overflowY: props.data?.length > 0 ? 'scroll' : 'hidden', // overflowY: props.data?.length > 0 ? 'auto' : 'hidden', maxHeight: toPx(props.scroll.y) }; } if (horizonScroll.value) { // scrollXStyle.value = { overflowX: props.data?.length > 0 ? 'auto' : 'hidden' }; // When no vertical scrollbar, should hide it // https://github.com/ant-design/ant-design/pull/20705 // https://github.com/ant-design/ant-design/issues/21879 if (!fixHeader.value) { // scrollYStyle.value = { overflowY: 'hidden' }; } scrollTableStyle.value = { // width: props.scroll.x === true ? 'auto' : toPx(props.scroll.x), minWidth: '100%' }; } }); var onColumnResize = function onColumnResize(columnKey, width) { if (isVisible(fullTableRef.value)) { updateColsWidths(function (widths) { if (widths.get(columnKey) !== width) { var newWidths = new Map(widths); newWidths.set(columnKey, width); return newWidths; } return widths; }); } }; var _useTimeoutLock = useTimeoutLock(null), _useTimeoutLock2 = _slicedToArray(_useTimeoutLock, 2), setScrollTarget = _useTimeoutLock2[0], getScrollTarget = _useTimeoutLock2[1]; function forceScroll(scrollLeft, target) { if (!target) { return; } if (typeof target === 'function') { target(scrollLeft); return; } var domTarget = target.$el || target; if (domTarget.scrollLeft !== scrollLeft) { // eslint-disable-next-line no-param-reassign domTarget.scrollLeft = scrollLeft; } } var onScroll = function onScroll(_ref3) { var currentTarget = _ref3.currentTarget, scrollLeft = _ref3.scrollLeft; var isRTL = props.direction === 'rtl'; var mergedScrollLeft = typeof scrollLeft === 'number' ? scrollLeft : currentTarget.scrollLeft; var compareTarget = currentTarget || EMPTY_SCROLL_TARGET; if (!getScrollTarget() || getScrollTarget() === compareTarget) { var _stickyRef$value; setScrollTarget(compareTarget); // forceScroll(mergedScrollLeft, scrollHeaderRef.value); forceScroll(mergedScrollLeft, scrollBodyRef.value); forceScroll(mergedScrollLeft, scrollSummaryRef.value); forceScroll(mergedScrollLeft, (_stickyRef$value = stickyRef.value) === null || _stickyRef$value === void 0 ? void 0 : _stickyRef$value.setScrollLeft); } if (currentTarget) { var scrollWidth = currentTarget.scrollWidth, clientWidth = currentTarget.clientWidth; if (isRTL) { setPingedLeft(-mergedScrollLeft < scrollWidth - clientWidth); setPingedRight(-mergedScrollLeft > 0); } else { setPingedLeft(mergedScrollLeft > 0); setPingedRight(mergedScrollLeft < scrollWidth - clientWidth); } } }; var triggerOnScroll = function triggerOnScroll() { if (horizonScroll.value && scrollBodyRef.value) { onScroll({ currentTarget: scrollBodyRef.value }); } else { setPingedLeft(false); setPingedRight(false); } }; var timtout; var updateWidth = function updateWidth(width) { if (width !== componentWidth.value) { triggerOnScroll(); componentWidth.value = fullTableRef.value ? fullTableRef.value.offsetWidth : width; } }; var onFullTableResize = function onFullTableResize(_ref4) { var width = _ref4.width; clearTimeout(timtout); if (componentWidth.value === 0) { updateWidth(width); return; } timtout = setTimeout(function () { updateWidth(width); }, 100); // 表格宽度发生变化时初始化表格滚动状态 onInitTableScroll(); }; var isScrollBar = ref(false); watch([horizonScroll, function () { return props.data; }, function () { return props.columns; }], function () { if (horizonScroll.value) { triggerOnScroll(); } nextTick(function () { var _scrollBodyRef$value, _scrollBodyRef$value$, _scrollBodyRef$value2; isScrollBar.value = ((_scrollBodyRef$value = scrollBodyRef.value) === null || _scrollBodyRef$value === void 0 ? void 0 : (_scrollBodyRef$value$ = _scrollBodyRef$value.querySelector('table')) === null || _scrollBodyRef$value$ === void 0 ? void 0 : _scrollBodyRef$value$.offsetHeight) > ((_scrollBodyRef$value2 = scrollBodyRef.value) === null || _scrollBodyRef$value2 === void 0 ? void 0 : _scrollBodyRef$value2.offsetHeight); // columns发生变化时初始化表格滚动状态 onInitTableScroll(); }); }, { flush: 'post' }); var onInitTableScroll = function onInitTableScroll() { var _fullTableRef$value$c, _fullTableRef$value; var bodyMinWidth = 0; flattenColumns.value.forEach(function (column) { bodyMinWidth += Number(column.width || column.minWidth || 0); }); var bodyWidth = (_fullTableRef$value$c = (_fullTableRef$value = fullTableRef.value) === null || _fullTableRef$value === void 0 ? void 0 : _fullTableRef$value.clientWidth) !== null && _fullTableRef$value$c !== void 0 ? _fullTableRef$value$c : 0; var selectColumn = flattenColumns.value.find(function (column) { return INTERNAL_COL_DEFINE in column; }); if (selectColumn !== null && selectColumn !== void 0 && selectColumn.className && fullTableRef.value) { var selectEl = fullTableRef.value.querySelector(".".concat(selectColumn.className)); var selectRect = selectEl.getBoundingClientRect(); bodyWidth = bodyWidth - selectRect.width; } layout.scrollX = bodyMinWidth > bodyWidth; syncPosition(); }; var _useState5 = useState(0), _useState6 = _slicedToArray(_useState5, 2), scrollbarSize = _useState6[0], setScrollbarSize = _useState6[1]; useProvideSticky(); onMounted(function () { nextTick(function () { var _scrollBodyRef$value3, _scrollBodyRef$value4; triggerOnScroll(); setScrollbarSize(getTargetScrollBarSize(scrollBodyRef.value).width); scrollBodySizeInfo.value = { scrollWidth: ((_scrollBodyRef$value3 = scrollBodyRef.value) === null || _scrollBodyRef$value3 === void 0 ? void 0 : _scrollBodyRef$value3.scrollWidth) || 0, clientWidth: ((_scrollBodyRef$value4 = scrollBodyRef.value) === null || _scrollBodyRef$value4 === void 0 ? void 0 : _scrollBodyRef$value4.clientWidth) || 0 }; onInitTableScroll(); }); }); onUpdated(function () { nextTick(function () { var _scrollBodyRef$value5, _scrollBodyRef$value6, _props$virtualScroll; var scrollWidth = ((_scrollBodyRef$value5 = scrollBodyRef.value) === null || _scrollBodyRef$value5 === void 0 ? void 0 : _scrollBodyRef$value5.scrollWidth) || 0; var clientWidth = ((_scrollBodyRef$value6 = scrollBodyRef.value) === null || _scrollBodyRef$value6 === void 0 ? void 0 : _scrollBodyRef$value6.clientWidth) || 0; if (scrollBodySizeInfo.value.scrollWidth !== scrollWidth || scrollBodySizeInfo.value.clientWidth !== clientWidth) { scrollBodySizeInfo.value = { scrollWidth: scrollWidth, clientWidth: clientWidth }; } if ((_props$virtualScroll = props.virtualScroll) !== null && _props$virtualScroll !== void 0 && _props$virtualScroll.isOpen) { virtualScrollInit(); } }); }); // 记录得到每一行容器尺寸大小 var sizeMap = new Map(); // 记录得到每一行被合并的首项下标和结束下标 var rowspanStartEndIndexMap = new Map(); var requestAnimationFrame = getRequestAnimationFrame(); var virtualScrollRafId = null; var cancelVirtualScrollSchedule = function cancelVirtualScrollSchedule() { if (virtualScrollRafId !== null) { cancelRequestAnimationFrame(virtualScrollRafId); virtualScrollRafId = null; } }; // 组件卸载时清理资源 onBeforeUnmount(function () { if (timtout) clearTimeout(timtout); cancelVirtualScrollSchedule(); // 清理Map缓存,避免内存堆积 sizeMap.clear(); rowspanStartEndIndexMap.clear(); }); watchEffect(function () { if (props.internalHooks === INTERNAL_HOOKS && props.internalRefs) { props.onUpdateInternalRefs({ body: scrollBodyRef.value ? scrollBodyRef.value.$el || scrollBodyRef.value : null }); } }, { flush: 'post' }); // Table layout var mergedTableLayout = computed(function () { if (props.tableLayout) { return props.tableLayout; } // https://github.com/ant-design/ant-design/issues/25227 // When scroll.x is max-content, no need to fix table layout // it's width should stretch out to fit content if (fixColumn.value) { return props.scroll.x === 'max-content' ? 'auto' : 'fixed'; } if (fixHeader.value || stickyState.value.isSticky || flattenColumns.value.some(function (_ref5) { var ellipsis = _ref5.ellipsis; return ellipsis; })) { return 'fixed'; } return 'auto'; }); var emptyNode = function emptyNode() { var _slots$emptyText; return hasData.value ? null : ((_slots$emptyText = slots.emptyText) === null || _slots$emptyText === void 0 ? void 0 : _slots$emptyText.call(slots)) || 'No Data'; }; useProvideTable(reactive(_objectSpread(_objectSpread({}, toRefs(reactivePick(props, 'prefixCls', 'direction', 'transformCellText'))), {}, { getComponent: getComponent, scrollbarSize: scrollbarSize, fixedInfoList: computed(function () { return flattenColumns.value.map(function (_, colIndex) { return getCellFixedInfo(colIndex, colIndex, flattenColumns.value, stickyOffsets.value, props.direction); }); }), isSticky: computed(function () { return stickyState.value.isSticky; }), summaryCollect: summaryCollect }))); useProvideBody(reactive(_objectSpread(_objectSpread({}, toRefs(reactivePick(props, 'rowClassName', 'expandedRowClassName', 'expandRowByClick', 'expandedRowRender', 'expandIconColumnIndex', 'indentSize'))), {}, { columns: columns, flattenColumns: flattenColumns, tableLayout: mergedTableLayout, expandIcon: mergedExpandIcon, expandableType: expandableType, onTriggerExpand: onTriggerExpand }))); useProvideResize({ onColumnResize: onColumnResize }); useProvideInitScroll({ onInitTableScroll: onInitTableScroll }); provide(ResizeColumnMoveRefKey, resizeColumnMoveRef); provide(FullTableRefKey, fullTableRef); provide(HasDataKey, hasData); provide(ResizeColumnStartRefKey, resizeColumnStartRef); provide(ResizeColumnStatusKey, isResizingHandle); useProvideExpandedRow({ componentWidth: componentWidth, fixHeader: fixHeader, fixColumn: fixColumn, horizonScroll: horizonScroll }); // 滚动时同步表头位置 var handleScrollBar = function handleScrollBar() { syncPosition(); }; var hasScrollClass = function hasScrollClass(className) { return !!(fullTableRef.value && fullTableRef.value.classList.contains(className)); }; // 高度变化 var dymysicHeight = shallowRef(0); var list = customRef(function (track, trigger) { return { get: function get() { var _props$virtualScroll2; track(); return !((_props$virtualScroll2 = props.virtualScroll) !== null && _props$virtualScroll2 !== void 0 && _props$virtualScroll2.isOpen) ? mergedData.value : mergedData.value.slice(saveIndex.value.startIndex, saveIndex.value.endIndex); }, set: function set() { trigger(); } }; }); var rowHeight = ref(32); // 默认32 // 计算出每一个item到滚动容器顶部的距离 var offsetMap = function offsetMap() { var res = {}; var total = 0; for (var i = 0; i < mergedData.value.length; i++) { var _mergedData$value; var val = (_mergedData$value = mergedData.value) === null || _mergedData$value === void 0 ? void 0 : _mergedData$value[i]; var key = getRowKey.value(val); res[key] = total; var curSize = sizeMap.get(key); var size = typeof curSize === 'number' ? curSize : rowHeight.value; total += size; } return res; }; var isTreeStructure = function isTreeStructure(listData) { return listData.some(function (k) { return (k === null || k === void 0 ? void 0 : k[mergedChildrenColumnName.value]) && Array.isArray(k === null || k === void 0 ? void 0 : k[mergedChildrenColumnName.value]); }); }; // 更新每行的纵向合并首项 var updateRowSpan = function updateRowSpan() { var rows = []; if (isTreeStructure(list.value)) { var _scrollBodyRef$value7; // add: 需要判断是否为树状结构 rows = (_scrollBodyRef$value7 = scrollBodyRef.value) === null || _scrollBodyRef$value7 === void 0 ? void 0 : _scrollBodyRef$value7.querySelectorAll(".".concat(props.prefixCls, "-body .").concat(props.prefixCls, "-tbody .").concat(props.prefixCls, "-row-level-0")); } else { var _scrollBodyRef$value8; rows = (_scrollBodyRef$value8 = scrollBodyRef.value) === null || _scrollBodyRef$value8 === void 0 ? void 0 : _scrollBodyRef$value8.querySelectorAll(".".concat(props.prefixCls, "-body .").concat(props.prefixCls, "-tbody .").concat(props.prefixCls, "-row")); } if (!rows) return; Array.prototype.forEach.call(rows, function (row, idx) { var item = list.value[idx]; if (!item) return; // 获取当前行的所有有rowspan的cell var rowspanCellList = row === null || row === void 0 ? void 0 : row.querySelectorAll(".".concat(props.prefixCls, "-cell-is-row-span")); // 获取cell中的所有rowspan,并给被合并项标记合并首项的最小值 Array.prototype.forEach.call(rowspanCellList, function (cell) { var rowspan = +cell.getAttribute('rowspan'); var startIndex = saveIndex.value.startIndex + idx; var endIndex = startIndex + rowspan - 1; for (var i = 0; i < rowspan; i++) { var val = mergedData.value[startIndex + i]; if (!val) return; var key = getRowKey.value(val); var rowspanStartIndex = rowspanStartEndIndexMap.get(key); if (rowspanStartIndex) { var _rowspanStartIndex = _slicedToArray(rowspanStartIndex, 2), start = _rowspanStartIndex[0], end = _rowspanStartIndex[1]; var startVal = Math.min(start, startIndex); var EndVal = Math.max(end, endIndex); rowspanStartEndIndexMap.set(key, [startVal, EndVal]); } else { rowspanStartEndIndexMap.set(key, [startIndex, endIndex]); } } }); }); }; var getRowSpan = function getRowSpan(start, end, searchIndex) { var _mergedData$value2, _rowspanStartEndIndex; var item = (_mergedData$value2 = mergedData.value) === null || _mergedData$value2 === void 0 ? void 0 : _mergedData$value2[searchIndex]; if (!item) return [start, end]; var key = getRowKey.value(item); var val = (_rowspanStartEndIndex = rowspanStartEndIndexMap.get(key)) !== null && _rowspanStartEndIndex !== void 0 ? _rowspanStartEndIndex : [start, end]; return val; }; // 更新每一行动态尺寸 var updateSize = function updateSize() { var rows = []; if (isTreeStructure(list.value)) { var _scrollBodyRef$value9; // add: 需要判断是否为树状结构 rows = (_scrollBodyRef$value9 = scrollBodyRef.value) === null || _scrollBodyRef$value9 === void 0 ? void 0 : _scrollBodyRef$value9.querySelectorAll(".".concat(props.prefixCls, "-body .").concat(props.prefixCls, "-tbody .").concat(props.prefixCls, "-row-level-0")); } else { var _scrollBodyRef$value10; // todo: 如果是树形结构需要计算嵌套基层并加上里面嵌套层高度 rows = (_scrollBodyRef$value10 = scrollBodyRef.value) === null || _scrollBodyRef$value10 === void 0 ? void 0 : _scrollBodyRef$value10.querySelectorAll(".".concat(props.prefixCls, "-body .").concat(props.prefixCls, "-tbody .").concat(props.prefixCls, "-row")); } if (!rows) return; var rowHeights = []; Array.prototype.forEach.call(rows, function (row, idx) { var _props$virtualScroll3; var item = list.value[idx]; if (!item) return; // 计算表格行的高度 var offsetHeightRow = row.offsetHeight; rowHeights.push(offsetHeightRow); if (!((_props$virtualScroll3 = props.virtualScroll) !== null && _props$virtualScroll3 !== void 0 && _props$virtualScroll3.isDynamic)) return; // 如果表格行有扩展项,需要加上扩张向的高度 var nextRow = row === null || row === void 0 ? void 0 : row.nextElementSibling; if (nextRow && nextRow.classList && nextRow.classList.contains("".concat(props.prefixCls, "-expanded-row"))) { offsetHeightRow += nextRow.nextElementSibling.offsetHeight; } // 表格行如果有子孙节点,需要加上子孙节点 高度 var next = row === null || row === void 0 ? void 0 : row.nextElementSibling; while (!!next && next.tagName === 'TR' && !next.classList.contains("".concat(props.prefixCls, "-row-level-0"))) { offsetHeightRow += next.offsetHeight; next = next.nextElementSibling; } var key = getRowKey.value(item); if (sizeMap.get(key) !== offsetHeightRow) { sizeMap.set(item.key, offsetHeightRow); row._offsetHeight = offsetHeightRow; } }); }; // 设置滚动状态方向 var setScrollDirection = function setScrollDirection(direction) { Object.keys(scrollDirection).forEach(function (key) { if (key === direction) { scrollDirection[direction] = true; } else { scrollDirection[key] = false; } }); }; var saveIndex = ref({ startIndex: 0, endIndex: 0 }); var positiontransformY = shallowRef(0); // 获取某条数据的尺寸 var getItemSize = function getItemSize(index) { var _list$value; // 先从缓存中获取 if (index < 0) return 0; var item = (_list$value = list.value) === null || _list$value === void 0 ? void 0 : _list$value[index]; if (item) { var _sizeMap$get; var key = getRowKey.value(item); return (_sizeMap$get = sizeMap.get(key)) !== null && _sizeMap$get !== void 0 ? _sizeMap$get : rowHeight.value; } return rowHeight.value; }; // 获取某条数据的offsetTop var getItemOffsetTop = function getItemOffsetTop(index) { var _props$virtualScroll4, _mergedData$value3; // 固定行高就直接相乘计算 if (!((_props$virtualScroll4 = props.virtualScroll) !== null && _props$virtualScroll4 !== void 0 && _props$virtualScroll4.isDynamic)) { return index * rowHeight.value; } var item = (_mergedData$value3 = mergedData.value) === null || _mergedData$value3 === void 0 ? void 0 : _mergedData$value3[index]; if (item) { var _obj$key; var obj = offsetMap(); var key = getRowKey.value(item); return (_obj$key = obj[key]) !== null && _obj$key !== void 0 ? _obj$key : 32; } return 0; }; // 计算动态滚动高度 var calcPositionFun = function calcPositionFun() { var last = mergedData.value.length - 1; // 计算内容总高度 var totalHeight = getItemOffsetTop(last) + getItemSize(last); // 计算当前滚动位置需要撑起的高度 var offsetTop = getItemOffsetTop(saveIndex.value.startIndex); dymysicHeight.value = totalHeight; positiontransformY.value = offsetTop; }; // 计算视图上渲染的数据位置 var getCalcRenderData = function getCalcRenderData() { var _props$virtualScroll5; var scrollContainer = scrollBarRef.value.wrapRef; var scrollTop = scrollContainer.scrollTop, offsetHeight = scrollContainer.offsetHeight; // 先默认固定缓存5条32*5=160 var BUFFER = ((_props$virtualScroll5 = props.virtualScroll) === null || _props$virtualScroll5 === void 0 ? void 0 : _props$virtualScroll5.buffer) || 0; var top = Math.max(scrollTop - BUFFER, 0); // 可视区底部 var bottom = scrollTop + offsetHeight + BUFFER; var start; var end; // 这里区分动态计算行高度,不定高的情况 目前固定为动态计算 var l = 0; var r = mergedData.value.length - 1; var mid = 0; // 二分法查找滚动最优项 while (l <= r) { // 当先位置到底部之间的中间值,向下取整 mid = Math.floor((l + r) / 2); // 计算中间数据距离顶部距离 var midVal = getItemOffsetTop(mid); if (midVal < top) { var midNextVal = getItemOffsetTop(mid + 1); if (midNextVal > top) break; l = mid + 1; } else { r = mid - 1; } } // 计算渲染内容的开始、结束索引 start = mid; end = mergedData.value.length; for (var i = start + 1; i < mergedData.value.length; i++) { var offsetTop = getItemOffsetTop(i); if (offsetTop >= bottom) { end = i; break; } } // 如果当前首项是被合并项,则start要取合并首项,end取合并尾项 start = Math.min(mid, getRowSpan(mid, end, mid)[0]); end = Math.max(end, getRowSpan(start, end, end)[1] + 1); // 开始索引始终保持偶数,如果为奇数,则加1使其保持偶数【确保表格行的偶数数一致,不会导致斑马纹乱序显示】 if (start % 2) { start = start - 1; } saveIndex.value.startIndex = start; saveIndex.value.endIndex = end; }; var runVirtualScrollTasks = function runVirtualScrollTasks() { var _props$virtualScroll6; if (!((_props$virtualScroll6 = props.virtualScroll) !== null && _props$virtualScroll6 !== void 0 && _props$virtualScroll6.isOpen)) { return; } updateRowSpan(); updateSize(); getCalcRenderData(); calcPositionFun(); }; var virtualScrollInit = function virtualScrollInit() { var _props$virtualScroll7; if (!((_props$virtualScroll7 = props.virtualScroll) !== null && _props$virtualScroll7 !== void 0 && _props$virtualScroll7.isOpen)) { return; } cancelVirtualScrollSchedule(); virtualScrollRafId = requestAnimationFrame(function () { virtualScrollRafId = null; runVirtualScrollTasks(); }); }; var syncPosition = function syncPosition() { var _props$virtualScroll8; if (!scrollBarRef.value) return; var scrollContainer = scrollBarRef.value.wrapRef; var scrollLeft = scrollContainer.scrollLeft, offsetWidth = scrollContainer.offsetWidth, scrollWidth = scrollContainer.scrollWidth; if ((_props$virtualScroll8 = props.virtualScroll) !== null && _props$virtualScroll8 !== void 0 && _props$virtualScroll8.isOpen) { virtualScrollInit(); } if (!layout.scrollX) { var scrollingNoneClass = 'is-scrolling-none'; if (!hasScrollClass(scrollingNoneClass)) { setScrollDirection(); } return; } if (!scrollContainer) return; if (scrollHeaderRef.value) scrollHeaderRef.value.$el.scrollLeft = scrollLeft; var maxScrollLeftPosition = scrollWidth - offsetWidth - 1; if (scrollLeft >= maxScrollLeftPosition) { setScrollDirection('right'); } else if (scrollLeft === 0) { setScrollDirection('left'); } else { setScrollDirection('middle'); } }; // 获取滚动条实例方法 var getScrollbar = function getScrollbar() { return scrollBarRef.value; }; expose({ getScrollbar: getScrollbar }); // Body var bodyTable = function bodyTable() { var _props$virtualScroll9; return _createVNode(Body, { "data": list.value, "measureColumnWidth": fixHeader.value || horizonScroll.value || stickyState.value.isSticky, "expandedKeys": mergedExpandedKeys.value, "rowExpandable": props.rowExpandable, "getRowKey": getRowKey.value, "customRow": props.customRow, "childrenColumnName": mergedChildrenColumnName.value, "style": (_props$virtualScroll9 = props.virtualScroll) !== null && _props$virtualScroll9 !== void 0 && _props$virtualScroll9.isOpen ? { transform: "translateY(".concat(positiontransformY.value, "px)") } : null }, { emptyNode: emptyNode }); }; var bodyColGroup = function bodyColGroup() { return _createVNode(ColGroup, { "colWidths": flattenColumns.value.map(function (_ref6) { var width = _ref6.width; return width; }), "columns": flattenColumns.value }, null); }; // 滚动条内容区域样式 var scrollbarStyle = computed(function () { if (!mergedData.value.length) { return { overflow: 'hidden' }; } if (props.scroll.y) { return props.isMaxHeight ? _objectSpread({ height: '100%' }, scrollYStyle.value) : { height: '100%' }; } return {}; }); // 滚动条视图区域样式 var scrollbarViewStyle = props.isScrollPosition ? { display: 'inline-block', verticalAlign: 'middle', position: 'relative' } : { display: 'inline-block', verticalAlign: 'middle' }; return function () { var _slots$summary; var prefixCls = props.prefixCls, scroll = props.scroll, tableLayout = props.tableLayout, direction = props.direction, _props$title = props.title, title = _props$title === void 0 ? slots.title : _props$title, _props$footer = props.footer, footer = _props$footer === void 0 ? slots.footer : _props$footer, id = props.id, showHeader = props.showHeader, customHeaderRow = props.customHeaderRow; var _stickyState$value = stickyState.value, isSticky = _stickyState$value.isSticky, offsetHeader = _stickyState$value.offsetHeader, offsetSummary = _stickyState$value.offsetSummary, offsetScroll = _stickyState$value.offsetScroll, stickyClassName = _stickyState$value.stickyClassName, container = _stickyState$value.container; var TableComponent = getComponent(['table'], 'table'); var customizeScrollBody = getComponent(['body']); var summaryNode = (_slots$summary = slots.summary) === null || _slots$summary === void 0 ? void 0 : _slots$summary.call(slots, { pageData: mergedData.value }); var groupTableNode = function groupTableNode() { return null; }; // Header props var headerProps = { colWidths: colWidths.value, columCount: flattenColumns.value.length, stickyOffsets: stickyOffsets.value, customHeaderRow: customHeaderRow, fixHeader: fixHeader.value, scroll: scroll }; if (process.env.NODE_ENV !== 'production' && typeof customizeScrollBody === 'function' && hasData.value && !fixHeader.value) { warning(false, '`components.body` with render props is only work on `scroll.y`.'); } if (fixHeader.value || isSticky) { // >>>>>> Fixed Header var bodyContent = function bodyContent() { return null; }; if (typeof customizeScrollBody === 'function') { bodyContent = function bodyContent() { return customizeScrollBody(mergedData.value, { scrollbarSize: scrollbarSize.value, ref: scrollBodyRef, onScroll: onScroll }); }; headerProps.colWidths = flattenColumns.value.map(function (_ref7, index) { var width = _ref7.width; var colWidth = index === columns.value.length - 1 ? width - scrollbarSize.value : width; if (typeof colWidth === 'number' && !Number.isNaN(colWidth)) { return colWidth; } warning(false, 'When use `components.body` with render props. Each column should have a fixed `width` value.'); return 0; }); } else { var scrollbarInlineStyle = null; if (props.isMaxHeight) { scrollbarInlineStyle = _objectSpread({}, scrollYStyle.value); } bodyContent = function bodyContent() { var _props$virtualScroll10; return _createVNode("div", { "style": _objectSpread({}, scrollYStyle.value), "ref": scrollBodyRef, "class": classNames("".concat(prefixCls, "-body")) }, [_createVNode(ScrollBar, { "style": scrollbarInlineStyle, "ref": scrollBarRef, "wrap-style": scrollbarStyle.value, "view-style": scrollbarViewStyle, "onScroll": handleScrollBar }, { default: function _default() { return [_createVNode(TableComponent, { "style": _objectSpread(_objectSpread({}, scrollTableStyle.value), {}, { tableLayout: mergedTableLayout.value }) }, { default: function _default() { return [(_props$virtualScroll10 = props.virtualScroll) !== null && _props$virtualScroll10 !== void 0 && _props$virtualScroll10.isOpen ? _createVNode("div", { "style": { height: dymysicHeight.value + 'px', position: 'absolute', width: '100%', zIndex: -1 } }, null) : null, bodyColGroup(), bodyTable(), !fixFooter.value && summaryNode && _createVNode(Footer, { "stickyOffsets": stickyOffsets.value, "flattenColumns": flattenColumns.value }, { default: function _default() { return [summaryNode]; } })]; } })]; } })]); }; } // Fixed holder share the props var fixedHolderProps = _objectSpread(_objectSpread(_objectSpread({ noData: !mergedData.value.length, maxContentScroll: horizonScroll.value && scroll.x === 'max-content' }, headerProps), columnContext.value), {}, { direction: direction, stickyClassName: stickyClassName, onScroll: onScroll }); groupTableNode = function groupTableNode() { return _createVNode(_Fragment, null, [showHeader !== false && _createVNode(FixedHolder, _objectSpread(_objectSpread({}, fixedHolderProps), {}, { "stickyTopOffset": offsetHeader, "class": "".concat(prefixCls, "-header"), "isScrollBar": false, "ref": scrollHeaderRef }), { default: function _default(fixedHolderPassProps) { return _createVNode(_Fragment, null, [_createVNode(Header, fixedHolderPassProps, null), fixFooter.value === 'top' && _createVNode(Footer, fixedHolderPassProps, { default: function _default() { return [summaryNode]; } })]); } }), bodyContent(), fixFooter.value && fixFooter.value !== 'top' && _createVNode(FixedHolder, _objectSpread(_objectSpread({}, fixedHolderProps), {}, { "stickyBottomOffset": offsetSummary, "class": "".concat(prefixCls, "-summary"), "isScrollBar": false, "ref": scrollSummaryRef }), { default: function _default(fixedHolderPassProps) { return _createVNode(Footer, fixedHolderPassProps, { default: function _default() { return [summaryNode]; } }); } }), isSticky && scrollBodyRef.value && _createVNode(StickyScrollBar, { "ref": stickyRef, "offsetScroll": offsetScroll, "scrollBodyRef": scrollBodyRef, "onScroll": onScroll, "container": container, "scrollBodySizeInfo": scrollBodySizeInfo.value }, null)]); }; } else { // >>>>>> Unique table groupTableNode = function groupTableNode() { return _createVNode("div", { "style": _objectSpread(_objectSpread({}, scrollXStyle.value), scrollYStyle.value), "class": classNames("".concat(prefixCls, "-content")), "onScroll": onScroll, "ref": scrollBodyRef }, [_createVNode(TableComponent, { "style": _objectSpread(_objectSpread({}, scrollTableStyle.value), {}, { tableLayout: mergedTableLayout.value }) }, { default: function _default() { return [bodyColGroup(), showHeader !== false && _createVNode(Header, _objectSpread(_objectSpread({}, headerProps), columnContext.value), null), bodyTable(), summaryNode && _createVNode(Footer, { "stickyOffsets": stickyOffsets.value, "flattenColumns": flattenColumns.value }, { default: function _default() { return [summaryNode]; } })]; } })]); }; } var ariaProps = pickAttrs(attrs, { aria: true, data: true }); var fullTable = function fullTable() { var _classNames; return _createVNode("div", _objectSpread(_objectSpread({}, ariaProps), {}, { "class": classNames(prefixCls, (_classNames = {}, _defineProperty(_classNames, "".concat(prefixCls, "-rtl"), direction === 'rtl'), _defineProperty(_classNames, "".concat(prefixCls, "-ping-left"), pingedLeft.value), _defineProperty(_classNames, "".concat(prefixCls, "-ping-right"), pingedRight.value), _defineProperty(_classNames, "".concat(prefixCls, "-layout-fixed"), tableLayout === 'fixed'), _defineProperty(_classNames, "".concat(prefixCls, "-fixed-header"), fixHeader.value), _defineProperty(_classNames, "".concat(prefixCls, "-fixed-column"), fixColumn.value), _defineProperty(_classNames, "".concat(prefixCls, "-scroll-horizontal"), horizonScroll.value), _defineProperty(_classNames, "".concat(prefixCls, "-has-fix-left"), flattenColumns.value[0] && flattenColumns.value[0].fixed), _defineProperty(_classNames, "".concat(prefixCls, "-has-fix-right"), flattenColumns.value[columnCount.value - 1] && flattenColumns.value[columnCount.value - 1].fixed === 'right'), _defineProperty(_classNames, attrs.class, attrs.class), _defineProperty(_classNames, 'is-scrolling-left', scrollDirection.left), _defineProperty(_classNames, 'is-scrolling-right', scrollDirection.right), _defineProperty(_classNames, 'is-scrolling-middle', scrollDirection.middle), _defineProperty(_classNames, 'is-scrolling-none', !scrollDirection.left && !scrollDirection.middle && !scrollDirection.right), _defineProperty(_classNames, 'is-resizing-handle', isResizingHandle.value), _classNames)), "style": attrs.style, "id": id, "ref": fullTableRef }), [title && _createVNode(Panel, { "class": "".concat(prefixCls, "-title") }, { default: function _default() { return [title(mergedData.value)]; } }), _createVNode("div", { "class": "".concat(prefixCls, "-container") }, [groupTableNode()]), _createVNode("div", { "class": "".concat(prefixCls, "-resize-start"), "ref": resizeColumnStartRef }, null), _createVNode("div", { "class": "".concat(prefixCls, "-resize-move"), "ref": resizeColumnMoveRef }, null), footer && _createVNode(Panel, { "class": "".concat(prefixCls, "-footer") }, { default: function _default() { return [footer(mergedData.value)]; } })]); }; if (horizonScroll.value) { return _createVNode(VCResizeObserver, { "onResize": onFullTableResize }, { default: fullTable }); } return fullTable(); }; } });