vxe-table
Version:
A PC-end table component based on Vxe UI, supporting copy-paste, data pivot table, and high-performance virtual list table solution.
14,792 lines • 721 kB
JavaScript
import { h, reactive, ref, provide, inject, nextTick, Teleport, onActivated, onDeactivated, onBeforeUnmount, onUnmounted, watch, computed, onMounted } from 'vue';
import { defineVxeComponent } from '../../ui/src/comp';
import XEUtils from 'xe-utils';
import { initTpImg, getTpImg, isPx, isScale, hasClass, addClass, removeClass, wheelScrollTopTo, wheelScrollLeftTo, getEventTargetNode, getPaddingTopBottomSize, setScrollTop, setScrollLeft, toCssUnit, hasControlKey, checkTargetElement, hasEventInputTarget } from '../../ui/src/dom';
import { getLastZIndex, nextZIndex, hasChildrenList, getFuncText, isEnableConf, formatText, eqEmptyValue } from '../../ui/src/utils';
import { VxeUI } from '../../ui';
import { createReactData, createInternalData, getRowUniqueId, createRowId, clearTableAllStatus, getColumnList, toFilters, hasDeepKey, getRowkey, getRowid, rowToVisible, colToVisible, getCellValue, setCellValue, handleRowidOrRow, handleFieldOrColumn, toTreePathSeq, restoreScrollLocation, getRootColumn, getRefElem, getColReMinWidth, getColReMaxWidth, createHandleUpdateRowId, createHandleGetRowId, getCalcHeight, getCellRestHeight, getLastChildColumn, getRowMaxHeight, handleCustomStoreConfig, encodeRowid } from './util';
import { getSlotVNs } from '../../ui/src/vn';
import { moveRowAnimateToTb, clearRowAnimate, moveColAnimateToLr, clearColAnimate } from '../../ui/src/anime';
import { createComponentLog } from '../../ui/src/log';
import { getCrossTableDragRowInfo } from './store';
import Cell from './cell';
import TableBodyComponent from './body';
import TableHeaderComponent from './header';
import TableFooterComponent from './footer';
import { tableProps } from './props';
import { tableEmits } from './emits';
import TableCustomPanelComponent from '../module/custom/panel';
import TableFilterPanelComponent from '../module/filter/panel';
import TableImportPanelComponent from '../module/export/import-panel';
import TableExportPanelComponent from '../module/export/export-panel';
import TableMenuPanelComponent from '../module/menu/panel';
import '../module/filter/hook';
import '../module/menu/hook';
import '../module/edit/hook';
import '../module/export/hook';
import '../module/keyboard/hook';
import '../module/validator/hook';
import '../module/custom/hook';
import '../render';
const { warnLog, errLog } = createComponentLog('table');
const { getConfig, getIcon, getI18n, renderer, formats, createEvent, globalResize, interceptor, hooks, globalEvents, GLOBAL_EVENT_KEYS, useFns, renderEmptyElement } = VxeUI;
const supportMaxRow = 5e6;
const customStorageKey = 'VXE_CUSTOM_STORE';
const maxYHeight = 5e6;
const maxXWidth = 5e6;
const sourceType = 'table';
let crossTableDragRowObj = null;
export default defineVxeComponent({
name: 'VxeTable',
props: tableProps,
emits: tableEmits,
setup(props, context) {
const { slots, emit } = context;
const xID = XEUtils.uniqueId();
const browseObj = XEUtils.browse();
// 使用已安装的组件,如果未安装则不渲染
const VxeUILoadingComponent = VxeUI.getComponent('VxeLoading');
const VxeUITooltipComponent = VxeUI.getComponent('VxeTooltip');
const $xeModal = inject('$xeModal', null);
const $xeTabs = inject('$xeTabs', null);
const $xeParentTable = inject('$xeTable', null);
const $xeSplitter = inject('$xeSplitter', null);
const $xeGrid = inject('$xeGrid', null);
const $xeGantt = inject('$xeGantt', null);
const $xeGGWrapper = $xeGrid || $xeGantt;
const { computeSize } = useFns.useSize(props);
const crossTableDragRowInfo = getCrossTableDragRowInfo();
const reactData = reactive(createReactData());
const internalData = createInternalData();
let tableMethods = {};
let tablePrivateMethods = {};
const refElem = ref();
const refVarElem = ref();
const refTooltip = ref();
const refCommTooltip = ref();
const refValidTooltip = ref();
const refTableMenu = ref();
const refTableFilter = ref();
const refTableCustom = ref();
const refTableViewportElem = ref();
const refTableHeader = ref();
const refTableBody = ref();
const refTableFooter = ref();
const refTableLeftHeader = ref();
const refTableLeftBody = ref();
const refTableLeftFooter = ref();
const refTableRightHeader = ref();
const refTableRightBody = ref();
const refTableRightFooter = ref();
const refTeleportWrapper = ref();
const refPopupWrapperElem = ref();
const refCustomContainerElem = ref();
const refLeftContainer = ref();
const refRightContainer = ref();
const refColResizeBar = ref();
const refRowResizeBar = ref();
const refEmptyPlaceholder = ref();
const refDragTipElem = ref();
const refDragRowLineElem = ref();
const refDragColLineElem = ref();
const refRowExpandElem = ref();
const refRowExpandYSpaceElem = ref();
const refScrollXVirtualElem = ref();
const refScrollYVirtualElem = ref();
const refScrollXHandleElem = ref();
const refScrollXLeftCornerElem = ref();
const refScrollXRightCornerElem = ref();
const refScrollYHandleElem = ref();
const refScrollYTopCornerElem = ref();
const refScrollXWrapperElem = ref();
const refScrollYWrapperElem = ref();
const refScrollYBottomCornerElem = ref();
const refScrollXSpaceElem = ref();
const refScrollYSpaceElem = ref();
let $xeToolbar;
const computeTableId = computed(() => {
const { id } = props;
if (id) {
if (XEUtils.isFunction(id)) {
return `${id({ $table: $xeTable, $grid: $xeGrid, $gantt: $xeGantt }) || ''}`;
}
return `${id}`;
}
return '';
});
const computeRowField = computed(() => {
const rowOpts = computeRowOpts.value;
return `${props.rowId || rowOpts.keyField || '_X_ROW_KEY'}`;
});
const computeValidOpts = computed(() => {
const opts = Object.assign({}, getConfig().table.validConfig, props.validConfig);
// 兼容老版本
if (XEUtils.isBoolean(opts.showMessage)) {
opts.showErrorMessage = opts.showMessage;
}
return opts;
});
/**
* @deprecated
*/
const computeSXOpts = computed(() => {
const virtualXOpts = computeVirtualXOpts.value;
return virtualXOpts;
});
const computeScrollXThreshold = computed(() => {
const virtualXOpts = computeVirtualXOpts.value;
const { threshold } = virtualXOpts;
if (threshold) {
return XEUtils.toNumber(threshold);
}
return 0;
});
/**
* @deprecated
*/
const computeSYOpts = computed(() => {
const virtualYOpts = computeVirtualYOpts.value;
return virtualYOpts;
});
const computeVirtualXOpts = computed(() => {
const { virtualXConfig, scrollX } = props;
const globalVirtualXConfig = getConfig().table.virtualXConfig;
const globalScrollX = getConfig().table.scrollX;
if (virtualXConfig) {
return Object.assign({}, globalVirtualXConfig, virtualXConfig);
}
if (scrollX) {
// 已废弃,保留兼容
return Object.assign({}, globalScrollX, scrollX);
}
if (globalVirtualXConfig) {
return Object.assign({}, globalVirtualXConfig, virtualXConfig);
}
// 已废弃,保留兼容
return Object.assign({}, globalScrollX, scrollX);
});
const computeVirtualYOpts = computed(() => {
const { virtualYConfig, scrollY } = props;
const globalVirtualYConfig = getConfig().table.virtualYConfig;
const globalScrollY = getConfig().table.scrollY;
if (virtualYConfig) {
return Object.assign({}, globalVirtualYConfig, virtualYConfig);
}
if (scrollY) {
// 已废弃,保留兼容
return Object.assign({}, globalScrollY, scrollY);
}
if (globalVirtualYConfig) {
return Object.assign({}, globalVirtualYConfig, virtualYConfig);
}
// 已废弃,保留兼容
return Object.assign({}, globalScrollY, scrollY);
});
const computeScrollbarOpts = computed(() => {
return Object.assign({}, getConfig().table.scrollbarConfig, props.scrollbarConfig);
});
const computeScrollbarXOpts = computed(() => {
var _a;
const scrollbarOpts = computeScrollbarOpts.value;
return Object.assign({}, scrollbarOpts.x, ((_a = props.scrollbarConfig) === null || _a === void 0 ? void 0 : _a.x) || {});
});
const computeScrollbarYOpts = computed(() => {
var _a;
const scrollbarOpts = computeScrollbarOpts.value;
return Object.assign({}, scrollbarOpts.y, ((_a = props.scrollbarConfig) === null || _a === void 0 ? void 0 : _a.y) || {});
});
const computeScrollbarXToTop = computed(() => {
const scrollbarXOpts = computeScrollbarXOpts.value;
return scrollbarXOpts.position === 'top';
});
const computeScrollbarYToLeft = computed(() => {
const scrollbarYOpts = computeScrollbarYOpts.value;
return scrollbarYOpts.position === 'left';
});
const computeScrollYThreshold = computed(() => {
const virtualYOpts = computeVirtualYOpts.value;
const { threshold } = virtualYOpts;
if (threshold) {
return XEUtils.toNumber(threshold);
}
return 0;
});
const computeRowHeightMaps = computed(() => {
return reactData.rowHeightStore;
});
const computeDefaultRowHeight = computed(() => {
const vSize = computeSize.value;
const rowHeightMaps = computeRowHeightMaps.value;
return rowHeightMaps[vSize || 'default'] || 18;
});
const computeColumnOpts = computed(() => {
return Object.assign({}, getConfig().table.columnConfig, props.columnConfig);
});
const computeCurrentColumnOpts = computed(() => {
return Object.assign({}, getConfig().table.currentColumnConfig, props.currentColumnConfig);
});
const computeCellOpts = computed(() => {
const cellOpts = Object.assign({}, getConfig().table.cellConfig, props.cellConfig);
if (cellOpts.height) {
cellOpts.height = XEUtils.toNumber(cellOpts.height);
}
return cellOpts;
});
const computeHeaderCellOpts = computed(() => {
const headerCellOpts = Object.assign({}, getConfig().table.headerCellConfig, props.headerCellConfig);
const defaultRowHeight = computeDefaultRowHeight.value;
const cellOpts = computeCellOpts.value;
let headCellHeight = XEUtils.toNumber(getCalcHeight(headerCellOpts.height || cellOpts.height));
if ($xeGantt) {
const { computeTaskViewScales } = $xeGantt.getComputeMaps();
const taskViewScales = computeTaskViewScales.value;
if (taskViewScales && taskViewScales.length > 2) {
const ganttMinHeadCellHeight = defaultRowHeight / 2 * taskViewScales.length;
headCellHeight = Math.max(ganttMinHeadCellHeight, headCellHeight);
}
}
headerCellOpts.height = headCellHeight;
return headerCellOpts;
});
const computeFooterCellOpts = computed(() => {
const footerCellOpts = Object.assign({}, getConfig().table.footerCellConfig, props.footerCellConfig);
const cellOpts = computeCellOpts.value;
footerCellOpts.height = XEUtils.toNumber(getCalcHeight(footerCellOpts.height || cellOpts.height));
return footerCellOpts;
});
const computeRowOpts = computed(() => {
return Object.assign({}, getConfig().table.rowConfig, props.rowConfig);
});
const computeAggregateOpts = computed(() => {
return Object.assign({}, getConfig().table.aggregateConfig || getConfig().table.rowGroupConfig, props.aggregateConfig || props.rowGroupConfig);
});
const computeRowGroupOpts = computed(() => {
return computeAggregateOpts.value;
});
const computeAggregateMode = computed(() => {
const aggregateOpts = computeAggregateOpts.value;
return aggregateOpts.mode;
});
const computeAggregateAccuracyOpts = computed(() => {
return Object.assign({}, getConfig().table.aggregateAccuracyConfig, props.aggregateAccuracyConfig);
});
const computeCurrentRowOpts = computed(() => {
return Object.assign({}, getConfig().table.currentRowConfig, props.currentRowConfig);
});
const computeRowDragOpts = computed(() => {
return Object.assign({}, getConfig().table.rowDragConfig, props.rowDragConfig);
});
const computeColumnDragOpts = computed(() => {
return Object.assign({}, getConfig().table.columnDragConfig, props.columnDragConfig);
});
const computeResizeOpts = computed(() => {
return Object.assign({}, getConfig().table.resizeConfig, props.resizeConfig);
});
const computeResizableOpts = computed(() => {
return Object.assign({}, getConfig().table.resizableConfig, props.resizableConfig);
});
const computeSeqOpts = computed(() => {
return Object.assign({ startIndex: 0 }, getConfig().table.seqConfig, props.seqConfig);
});
const computeRadioOpts = computed(() => {
return Object.assign({}, getConfig().table.radioConfig, props.radioConfig);
});
const computeCheckboxOpts = computed(() => {
return Object.assign({}, getConfig().table.checkboxConfig, props.checkboxConfig);
});
const computeTooltipOpts = computed(() => {
return Object.assign({}, getConfig().tooltip, getConfig().table.tooltipConfig, props.tooltipConfig);
});
const computeHeaderTooltipOpts = computed(() => {
return Object.assign({}, getConfig().tooltip, getConfig().table.headerTooltipConfig, props.headerTooltipConfig);
});
const computeFooterTooltipOpts = computed(() => {
return Object.assign({}, getConfig().tooltip, getConfig().table.footerTooltipConfig, props.footerTooltipConfig);
});
const computeTableTipConfig = computed(() => {
const { tooltipStore } = reactData;
const tooltipOpts = computeTooltipOpts.value;
return Object.assign({}, tooltipOpts, tooltipStore.currOpts);
});
const computeValidTipConfig = computed(() => {
const tooltipOpts = computeTooltipOpts.value;
return Object.assign({}, tooltipOpts);
});
const computeEditOpts = computed(() => {
return Object.assign({}, getConfig().table.editConfig, props.editConfig);
});
const computeEditDirtyOpts = computed(() => {
return Object.assign({}, getConfig().table.editDirtyConfig, props.editDirtyConfig);
});
const computeSortOpts = computed(() => {
return Object.assign({ orders: ['asc', 'desc', null] }, getConfig().table.sortConfig, props.sortConfig);
});
const computeFilterOpts = computed(() => {
return Object.assign({}, getConfig().table.filterConfig, props.filterConfig);
});
const computeFloatingFilterOpts = computed(() => {
return Object.assign({}, getConfig().table.floatingFilterConfig, props.floatingFilterConfig);
});
const computeMouseOpts = computed(() => {
return Object.assign({}, getConfig().table.mouseConfig, props.mouseConfig);
});
const computeAreaOpts = computed(() => {
return Object.assign({}, getConfig().table.areaConfig, props.areaConfig);
});
const computeKeyboardOpts = computed(() => {
return Object.assign({}, getConfig().table.keyboardConfig, props.keyboardConfig);
});
const computeClipOpts = computed(() => {
return Object.assign({}, getConfig().table.clipConfig, props.clipConfig);
});
const computeUndoRedoHistoryOpts = computed(() => {
return Object.assign({}, getConfig().table.undoRedoHistoryConfig, props.undoRedoHistoryConfig);
});
const computeFNROpts = computed(() => {
const fnrOpts = computeFnrOpts.value;
return fnrOpts;
});
const computeFnrOpts = computed(() => {
return Object.assign({}, getConfig().table.fnrConfig, props.fnrConfig);
});
const computeMenuOpts = computed(() => {
return Object.assign({}, getConfig().table.menuConfig, props.menuConfig);
});
const computeLeftFixedWidth = computed(() => {
const { columnStore } = reactData;
const { leftList } = columnStore;
let leftWidth = 0;
for (let i = 0; i < leftList.length; i++) {
const column = leftList[i];
leftWidth += column.renderWidth;
}
return leftWidth;
});
const computeRightFixedWidth = computed(() => {
const { columnStore } = reactData;
const { rightList } = columnStore;
let leftWidth = 0;
for (let i = 0; i < rightList.length; i++) {
const column = rightList[i];
leftWidth += column.renderWidth;
}
return leftWidth;
});
// 合并列是否超越冻结列
const computeBodyMergeCoverFixed = computed(() => {
const { columnStore, mergeBodyFlag } = reactData;
const { mergeBodyList, visibleColumn } = internalData;
const { leftList, rightList } = columnStore;
const rscIndex = visibleColumn.length - rightList.length;
if (mergeBodyFlag && (leftList.length || rightList.length)) {
const lecIndex = leftList.length;
for (let i = 0; i < mergeBodyList.length; i++) {
const { col, colspan } = mergeBodyList[i];
if (col < lecIndex && col + colspan > lecIndex) {
return true;
}
else if (col < rscIndex && col + colspan > rscIndex) {
return true;
}
}
}
return false;
});
const computeIsHeaderRenderOptimize = computed(() => {
const { spanMethod, footerSpanMethod, showHeaderOverflow: allColumnHeaderOverflow } = props;
const { isGroup, scrollXLoad } = reactData;
let isOptimizeMode = false;
if (isGroup) {
// 分组表头
}
else {
// 如果是使用优化模式
if (scrollXLoad && allColumnHeaderOverflow) {
if (spanMethod || footerSpanMethod) {
// 如果不支持优化模式
}
else {
isOptimizeMode = true;
}
}
}
return isOptimizeMode;
});
const computeIsBodyRenderOptimize = computed(() => {
const { spanMethod, footerSpanMethod } = props;
const { scrollXLoad, scrollYLoad, isAllOverflow, expandColumn } = reactData;
const bodyMergeCoverFixed = computeBodyMergeCoverFixed.value;
const expandOpts = computeExpandOpts.value;
let isOptimizeMode = false;
// 如果是使用优化模式
if (scrollXLoad || scrollYLoad || isAllOverflow) {
// 如果是展开行,内联模式,不支持优化
// 如果是方法合并,不支持优化
// 如果固定列且配置式合并,不支持优化
if ((expandColumn && expandOpts.mode !== 'fixed') || bodyMergeCoverFixed || spanMethod || footerSpanMethod) {
// 如果不支持优化模式
}
else {
isOptimizeMode = true;
}
}
return isOptimizeMode;
});
const computeIsFooterRenderOptimize = computed(() => {
const { spanMethod, footerSpanMethod, showFooterOverflow: allColumnFooterOverflow } = props;
const { scrollXLoad } = reactData;
let isOptimizeMode = false;
// 如果是使用优化模式
if (scrollXLoad && allColumnFooterOverflow) {
if (spanMethod || footerSpanMethod) {
// 如果不支持优化模式
}
else {
isOptimizeMode = true;
}
}
return isOptimizeMode;
});
const computeHeaderMenu = computed(() => {
const menuOpts = computeMenuOpts.value;
const headerOpts = menuOpts.header;
return headerOpts && headerOpts.options ? headerOpts.options : [];
});
const computeBodyMenu = computed(() => {
const menuOpts = computeMenuOpts.value;
const bodyOpts = menuOpts.body;
return bodyOpts && bodyOpts.options ? bodyOpts.options : [];
});
const computeFooterMenu = computed(() => {
const menuOpts = computeMenuOpts.value;
const footerOpts = menuOpts.footer;
return footerOpts && footerOpts.options ? footerOpts.options : [];
});
const computeIsMenu = computed(() => {
const isContentMenu = computeIsContentMenu.value;
return isContentMenu;
});
const computeIsContentMenu = computed(() => {
const menuOpts = computeMenuOpts.value;
const headerMenu = computeHeaderMenu.value;
const bodyMenu = computeBodyMenu.value;
const footerMenu = computeFooterMenu.value;
return !!(props.menuConfig && isEnableConf(menuOpts) && (headerMenu.length || bodyMenu.length || footerMenu.length));
});
const computeMenuList = computed(() => {
const { ctxMenuStore } = reactData;
const rest = [];
ctxMenuStore.list.forEach((list) => {
list.forEach((item) => {
rest.push(item);
});
});
return rest;
});
const computeExportOpts = computed(() => {
return Object.assign({}, getConfig().table.exportConfig, props.exportConfig);
});
const computeImportOpts = computed(() => {
return Object.assign({}, getConfig().table.importConfig, props.importConfig);
});
const computePrintOpts = computed(() => {
return Object.assign({}, getConfig().table.printConfig, props.printConfig);
});
const computeExpandOpts = computed(() => {
return Object.assign({}, getConfig().table.expandConfig, props.expandConfig);
});
const computeTreeOpts = computed(() => {
return Object.assign({}, getConfig().table.treeConfig, props.treeConfig);
});
const computeEmptyOpts = computed(() => {
return Object.assign({}, getConfig().table.emptyRender, props.emptyRender);
});
const computeLoadingOpts = computed(() => {
return Object.assign({}, getConfig().table.loadingConfig, props.loadingConfig);
});
const computeCellOffsetWidth = computed(() => {
return props.border ? Math.max(2, Math.ceil(reactData.scrollbarWidth / reactData.tableColumn.length)) : 1;
});
const computeCustomOpts = computed(() => {
return Object.assign({}, getConfig().table.customConfig, props.customConfig);
});
const computeCustomSimpleMode = computed(() => {
const { minHeight, height } = props;
const customOpts = computeCustomOpts.value;
const { mode, popupOptions, placement } = customOpts;
if (!placement || placement === 'top-left' || placement === 'top-right') {
if (!(mode === 'modal' || mode === 'drawer')) {
const { mode } = popupOptions || {};
if (!mode || mode === 'auto') {
if (height || minHeight) {
return 'inside';
}
return 'outside';
}
if (mode) {
return mode;
}
}
}
return '';
});
const computeTableStyle = computed(() => {
const scrollbarOpts = computeScrollbarOpts.value;
const { width, height } = scrollbarOpts;
const tStys = {};
if (width) {
tStys['--vxe-ui-table-view-scrollbar-width'] = toCssUnit(width);
}
if (height) {
tStys['--vxe-ui-table-view-scrollbar-height'] = toCssUnit(height);
}
return tStys;
});
const computeTableRowExpandedList = computed(() => {
const { tableData, rowExpandedFlag, expandColumn, rowGroupExpandedFlag, treeExpandedFlag } = reactData;
const { visibleDataRowIdData, rowExpandedMaps } = internalData;
const expandList = [];
if (tableData.length && expandColumn && rowExpandedFlag && rowGroupExpandedFlag && treeExpandedFlag) {
XEUtils.each(rowExpandedMaps, (row, rowid) => {
if (visibleDataRowIdData[rowid]) {
expandList.push(row);
}
});
}
return expandList;
});
const computeAutoWidthColumnList = computed(() => {
const { visibleColumn } = internalData;
const { tableColumn } = reactData;
return tableColumn.length || visibleColumn.length ? visibleColumn.filter(column => column.width === 'auto' || column.minWidth === 'auto') : [];
});
const computeFixedColumnSize = computed(() => {
const { tableColumn } = reactData;
const { collectColumn } = internalData;
let fixedSize = 0;
// 只判断第一层
if (tableColumn.length && collectColumn.length) {
collectColumn.forEach((column) => {
if (column.renderFixed) {
fixedSize++;
}
});
}
return fixedSize;
});
const computeIsMaxFixedColumn = computed(() => {
const fixedColumnSize = computeFixedColumnSize.value;
const columnOpts = computeColumnOpts.value;
const { maxFixedSize } = columnOpts;
if (maxFixedSize) {
return fixedColumnSize >= maxFixedSize;
}
return false;
});
const computeKeepFields = computed(() => {
const { tableFullColumn } = internalData;
const { updateColFlag } = reactData;
const editDirtyOpts = computeEditDirtyOpts.value;
const { extraFields, includeFields, excludeFields } = editDirtyOpts;
const kpFields = [];
if (updateColFlag) {
// 优先级 excludeFields > (includeFields || extraFields)
const excludeFdMaps = {};
if (excludeFields && excludeFields.length) {
excludeFields.forEach(field => {
excludeFdMaps[field] = 1;
});
}
if (includeFields && includeFields.length) {
return excludeFields && excludeFields.length ? includeFields.filter(field => !excludeFdMaps[field]) : includeFields;
}
const addFdMaps = {};
if (extraFields && extraFields.length) {
extraFields.forEach(field => {
if (!addFdMaps[field]) {
addFdMaps[field] = 1;
kpFields.push(field);
}
});
}
for (let i = 0; i < tableFullColumn.length; i++) {
const column = tableFullColumn[i];
const { field, type, editRender, cellRender } = column;
if (field && !type && (editRender || cellRender) && !addFdMaps[field] && !excludeFdMaps[field]) {
addFdMaps[field] = 1;
kpFields.push(field);
}
}
}
return kpFields;
});
const computeTableBorder = computed(() => {
const { border } = props;
if (border === true) {
return 'full';
}
if (border) {
return border;
}
return 'default';
});
const computeIsAllCheckboxDisabled = computed(() => {
const { treeConfig } = props;
const { tableData } = reactData;
const { tableFullData } = internalData;
const checkboxOpts = computeCheckboxOpts.value;
const { strict, checkMethod } = checkboxOpts;
if (strict) {
if (tableData.length || tableFullData.length) {
if (checkMethod) {
if (treeConfig) {
// 暂时不支持树形结构
}
// 如果所有行都被禁用
return tableFullData.every((row) => !checkMethod({ $table: $xeTable, row }));
}
return false;
}
return true;
}
return false;
});
const computeVirtualScrollBars = computed(() => {
const { overflowX, scrollXLoad, overflowY, scrollYLoad } = reactData;
return {
x: overflowX && scrollXLoad,
y: overflowY && scrollYLoad
};
});
const computeRowGroupFields = computed(() => {
const rowGroupOpts = computeRowGroupOpts.value;
return rowGroupOpts.groupFields;
});
const computeRowGroupColumns = computed(() => {
const { rowGroupList } = reactData;
const { fullColumnFieldData } = internalData;
const rgColumns = [];
rowGroupList.forEach(aggConf => {
const colRest = fullColumnFieldData[aggConf.field];
if (colRest) {
rgColumns.push(colRest.column);
}
});
return rgColumns;
});
const computeAggFuncColumns = computed(() => {
const { rowGroupList, tableColumn } = reactData;
if (rowGroupList.length) {
return tableColumn.filter(column => column.aggFunc);
}
return [];
});
const combineTabsResizeFlag = computed(() => {
return $xeTabs ? $xeTabs.reactData.resizeFlag : null;
});
const combineModalResizeFlag = computed(() => {
return $xeModal ? $xeModal.reactData.resizeFlag : null;
});
const combineSplitterResizeFlag = computed(() => {
return $xeSplitter ? $xeSplitter.reactData.resizeFlag : null;
});
const refMaps = {
refElem,
refTooltip,
refValidTooltip,
refTableFilter,
refTableCustom,
refTableMenu,
refTableHeader,
refTableBody,
refTableFooter,
refTableLeftHeader,
refTableLeftBody,
refTableLeftFooter,
refTableRightHeader,
refTableRightBody,
refTableRightFooter,
refLeftContainer,
refRightContainer,
refColResizeBar,
refRowResizeBar,
refCustomContainerElem,
refScrollXVirtualElem,
refScrollYVirtualElem,
refScrollXHandleElem,
refScrollYHandleElem,
refScrollXSpaceElem,
refScrollYSpaceElem
};
const computeMaps = {
computeSize,
computeTableId,
computeValidOpts,
computeRowField,
computeVirtualXOpts,
computeVirtualYOpts,
computeScrollbarOpts,
computeScrollbarXOpts,
computeScrollbarYOpts,
computeScrollbarXToTop,
computeScrollbarYToLeft,
computeColumnOpts,
computeCurrentColumnOpts,
computeScrollXThreshold,
computeScrollYThreshold,
computeRowHeightMaps,
computeDefaultRowHeight,
computeCellOpts,
computeHeaderCellOpts,
computeFooterCellOpts,
computeRowOpts,
computeAggregateOpts,
computeAggregateAccuracyOpts,
computeRowGroupOpts,
computeCurrentRowOpts,
computeRowDragOpts,
computeColumnDragOpts,
computeResizeOpts,
computeResizableOpts,
computeSeqOpts,
computeRadioOpts,
computeCheckboxOpts,
computeTooltipOpts,
computeHeaderTooltipOpts,
computeFooterTooltipOpts,
computeEditOpts,
computeEditDirtyOpts,
computeSortOpts,
computeFilterOpts,
computeFloatingFilterOpts,
computeMouseOpts,
computeAreaOpts,
computeKeyboardOpts,
computeClipOpts,
computeFnrOpts,
computeHeaderMenu,
computeBodyMenu,
computeFooterMenu,
computeIsMenu,
computeIsContentMenu,
computeMenuList,
computeMenuOpts,
computeExportOpts,
computeImportOpts,
computePrintOpts,
computeExpandOpts,
computeTreeOpts,
computeEmptyOpts,
computeLoadingOpts,
computeCellOffsetWidth,
computeCustomOpts,
computeCustomSimpleMode,
computeLeftFixedWidth,
computeRightFixedWidth,
computeBodyMergeCoverFixed,
computeFixedColumnSize,
computeIsMaxFixedColumn,
computeKeepFields,
computeIsAllCheckboxDisabled,
computeIsHeaderRenderOptimize,
computeIsBodyRenderOptimize,
computeIsFooterRenderOptimize,
computeVirtualScrollBars,
computeRowGroupFields,
computeRowGroupColumns,
computeAggFuncColumns,
computeUndoRedoHistoryOpts,
computeFNROpts,
computeSXOpts,
computeSYOpts
};
const $xeTable = {
xID,
props: props,
context,
reactData,
internalData,
getRefMaps: () => refMaps,
getComputeMaps: () => computeMaps,
xeGrid: $xeGrid,
xeGantt: $xeGantt,
// 已废弃
xegrid: $xeGrid
};
const eqCellValue = (newRow, oldRow, field) => {
const val1 = XEUtils.get(newRow, field);
const val2 = XEUtils.get(oldRow, field);
let result = false;
if (eqEmptyValue(val1) && eqEmptyValue(val2)) {
result = true;
}
else if (XEUtils.isString(val1) || XEUtils.isNumber(val1)) {
result = ('' + val1) === ('' + val2);
}
else {
result = XEUtils.isEqual(val1, val2);
}
return { newValue: val1, oldValue: val2, result };
};
const handleKeyField = () => {
const keyField = computeRowField.value;
internalData.currKeyField = keyField;
internalData.isCurrDeepKey = hasDeepKey(keyField);
};
const getNextSortOrder = (column) => {
const sortOpts = computeSortOpts.value;
const { orders = [] } = sortOpts;
const currOrder = column.order || null;
const oIndex = orders.indexOf(currOrder) + 1;
return orders[oIndex < orders.length ? oIndex : 0];
};
const getCustomStorageMap = (id) => {
const version = getConfig().version;
const rest = XEUtils.toStringJSON(localStorage.getItem(customStorageKey) || '');
const maps = rest && rest._v === version ? rest : { _v: version };
return (id ? maps[id] : maps) || {};
};
const setCustomStorageMap = (id, data) => {
const version = getConfig().version;
const maps = getCustomStorageMap();
maps[id] = data || undefined;
maps._v = version;
localStorage.setItem(customStorageKey, XEUtils.toJSONString(maps));
};
const getRecoverRowMaps = (keyMaps) => {
const { fullAllDataRowIdData } = internalData;
const restKeys = {};
XEUtils.each(keyMaps, (row, rowid) => {
if (fullAllDataRowIdData[rowid]) {
restKeys[rowid] = row;
}
});
return restKeys;
};
const handleReserveRow = (reserveRowMap) => {
const { fullDataRowIdData } = internalData;
const reserveList = [];
XEUtils.each(reserveRowMap, (item, rowid) => {
if (fullDataRowIdData[rowid] && $xeTable.findRowIndexOf(reserveList, fullDataRowIdData[rowid].row) === -1) {
reserveList.push(fullDataRowIdData[rowid].row);
}
});
return reserveList;
};
const handleVirtualXVisible = () => {
const { isScrollXBig, scrollXWidth } = reactData;
const { elemStore, visibleColumn, fullColumnIdData } = internalData;
const leftFixedWidth = computeLeftFixedWidth.value;
const rightFixedWidth = computeRightFixedWidth.value;
const bodyScrollElem = getRefElem(elemStore['main-body-scroll']);
if (bodyScrollElem) {
const clientWidth = bodyScrollElem.clientWidth;
let scrollLeft = bodyScrollElem.scrollLeft;
if (isScrollXBig) {
scrollLeft = Math.ceil((scrollXWidth - clientWidth) * Math.min(1, (scrollLeft / (maxXWidth - clientWidth))));
}
const startLeft = scrollLeft + leftFixedWidth;
const endLeft = scrollLeft + clientWidth - rightFixedWidth;
let leftIndex = 0;
let rightIndex = visibleColumn.length;
while (leftIndex < rightIndex) {
const cIndex = Math.floor((leftIndex + rightIndex) / 2);
const column = visibleColumn[cIndex];
const colid = column.id;
const colRest = fullColumnIdData[colid] || {};
if (colRest.oLeft <= startLeft) {
leftIndex = cIndex + 1;
}
else {
rightIndex = cIndex;
}
}
let visibleSize = 0;
const toVisibleIndex = leftIndex === visibleColumn.length ? leftIndex : Math.max(0, leftIndex < visibleColumn.length ? leftIndex - 2 : 0);
for (let cIndex = toVisibleIndex, cLen = visibleColumn.length; cIndex < cLen; cIndex++) {
const column = visibleColumn[cIndex];
const colid = column.id;
const colRest = fullColumnIdData[colid] || {};
visibleSize++;
if (colRest.oLeft > endLeft || visibleSize >= 60) {
break;
}
}
return { toVisibleIndex: Math.max(0, toVisibleIndex), visibleSize: Math.max(1, visibleSize) };
}
return { toVisibleIndex: 0, visibleSize: 6 };
};
const calcVarRowHeightConfig = (sizeKey, sizeEl) => {
const { rowHeightStore } = reactData;
if (sizeEl && sizeEl.clientHeight) {
rowHeightStore[sizeKey] = sizeEl.clientHeight;
}
};
const computeRowHeight = () => {
const { isAllOverflow } = reactData;
const tableHeader = refTableHeader.value;
const tableBody = refTableBody.value;
const tableBodyElem = tableBody ? tableBody.$el : null;
const defaultRowHeight = computeDefaultRowHeight.value;
let rowHeight = 0;
if (isAllOverflow) {
if (tableBodyElem) {
const tableHeaderElem = tableHeader ? tableHeader.$el : null;
let firstTrElem;
firstTrElem = tableBodyElem.querySelector('tr');
if (!firstTrElem && tableHeaderElem) {
firstTrElem = tableHeaderElem.querySelector('tr');
}
if (firstTrElem) {
rowHeight = firstTrElem.clientHeight;
}
}
if (!rowHeight) {
rowHeight = defaultRowHeight;
}
}
else {
rowHeight = defaultRowHeight;
}
// 最低支持 18px 行高
return Math.max(18, rowHeight);
};
const handleVirtualYVisible = () => {
const { isAllOverflow, expandColumn, isScrollYBig, scrollYHeight } = reactData;
const { elemStore, isResizeCellHeight, afterFullData, fullAllDataRowIdData } = internalData;
const rowOpts = computeRowOpts.value;
const cellOpts = computeCellOpts.value;
const defaultRowHeight = computeDefaultRowHeight.value;
const bodyScrollElem = getRefElem(elemStore['main-body-scroll']);
if (bodyScrollElem) {
const clientHeight = bodyScrollElem.clientHeight;
let scrollTop = bodyScrollElem.scrollTop;
if (isScrollYBig) {
scrollTop = Math.ceil((scrollYHeight - clientHeight) * Math.min(1, (scrollTop / (maxYHeight - clientHeight))));
}
const startTop = scrollTop;
const endTop = scrollTop + clientHeight;
let toVisibleIndex = -1;
let visibleSize = 0;
const isCustomCellHeight = isResizeCellHeight || cellOpts.height || rowOpts.height;
if (!isCustomCellHeight && !expandColumn && isAllOverflow) {
toVisibleIndex = Math.floor(startTop / defaultRowHeight) - 1;
visibleSize = Math.ceil(clientHeight / defaultRowHeight) + 1;
}
else {
const { handleGetRowId } = createHandleGetRowId($xeTable);
let leftIndex = 0;
let rightIndex = afterFullData.length;
while (leftIndex < rightIndex) {
const rIndex = Math.floor((leftIndex + rightIndex) / 2);
const row = afterFullData[rIndex];
const rowid = handleGetRowId(row);
const rowRest = fullAllDataRowIdData[rowid] || {};
if (rowRest.oTop <= startTop) {
leftIndex = rIndex + 1;
}
else {
rightIndex = rIndex;
}
}
toVisibleIndex = leftIndex === afterFullData.length ? leftIndex : Math.max(0, leftIndex < afterFullData.length ? leftIndex - 2 : 0);
for (let rIndex = toVisibleIndex, rLen = afterFullData.length; rIndex < rLen; rIndex++) {
const row = afterFullData[rIndex];
const rowid = handleGetRowId(row);
const rowRest = fullAllDataRowIdData[rowid] || {};
visibleSize++;
if (rowRest.oTop > endTop || visibleSize >= 100) {
break;
}
}
}
return { toVisibleIndex: Math.max(0, toVisibleIndex), visibleSize: Math.max(6, visibleSize) };
}
return { toVisibleIndex: 0, visibleSize: 6 };
};
const calculateMergerOffsetIndex = (list, mergeMaps, offsetItem, type) => {
const mKey = `${offsetItem.startIndex}:${offsetItem.endIndex}`;
const mObj = mergeMaps[mKey];
// 缓存
if (mObj) {
offsetItem.startIndex = mObj.startIndex;
offsetItem.endIndex = mObj.endIndex;
}
else {
for (let mcIndex = 0, len = list.length; mcIndex < len; mcIndex++) {
const mergeItem = list[mcIndex];
const { startIndex, endIndex } = offsetItem;
const mergeStartIndex = mergeItem[type];
const mergeSpanNumber = mergeItem[type + 'span'];
const mergeEndIndex = mergeStartIndex + mergeSpanNumber;
if (mergeStartIndex < startIndex && startIndex < mergeEndIndex) {
offsetItem.startIndex = mergeStartIndex;
}
if (mergeStartIndex < endIndex && endIndex < mergeEndIndex) {
offsetItem.endIndex = mergeEndIndex;
}
if (offsetItem.startIndex !== startIndex || offsetItem.endIndex !== endIndex) {
mcIndex = -1;
}
}
mergeMaps[mKey] = offsetItem;
}
};
function buildMergeData(mergeConfigs) {
const mergeMaps = {};
const mergeRowMaps = {};
const mergeColMaps = {};
if (mergeConfigs && mergeConfigs.length) {
for (let mIndex = 0; mIndex < mergeConfigs.length; mIndex++) {
const { row: _rowIndex, col: _columnIndex, rowspan: mergeRowspan, colspan: mergeColspan } = mergeConfigs[mIndex];
for (let i = 0; i < mergeRowspan; i++) {
const currRIndex = _rowIndex + i;
for (let j = 0; j < mergeColspan; j++) {
const currCIndex = _columnIndex + j;
mergeMaps[`${currRIndex}:${currCIndex}`] = !i && !j
? {
rowspan: mergeRowspan,
colspan: mergeColspan
}
: {
rowspan: 0,
colspan: 0
};
}
}
}
}
return { mergeMaps, mergeRowMaps, mergeColMaps };
}
const handleUpdateMergeBodyCells = (merges) => {
internalData.mergeBodyList = [];
internalData.mergeBodyMaps = {};
internalData.mergeBodyCellMaps = {};
internalData.mergeBodyRowMaps = {};
internalData.mergeBodyColMaps = {};
$xeTable.setMergeCells(merges);
};
const handleBodyMerge = (merges) => {
const { fullAllDataRowIdData, fullColumnIdData, visibleColumn, afterFullData, mergeBodyList, mergeBodyMaps } = internalData;
if (merges) {
const { handleGetRowId } = createHandleGetRowId($xeTable);
if (!XEUtils.isArray(merges)) {
merges = [merges];
}
merges.forEach((item) => {
let { row: margeRow, col: margeCol, rowspan, colspan } = item;
let mergeRowIndex = -1;
let mergeColumnIndex = -1;
if (XEUtils.isNumber(margeRow)) {
mergeRowIndex = margeRow;
}
else {
const rowid = margeRow ? handleGetRowId(margeRow) : null;
const rowRest = rowid ? fullAllDataRowIdData[rowid] : null;
if (rowRest) {
mergeRowIndex = rowRest._index;
}
}
if (XEUtils.isNumber(margeCol)) {
mergeColumnIndex = margeCol;
}
else {
const colid = margeCol ? margeCol.id : null;
const colRest = colid ? fullColumnIdData[colid] : null;
if (colRest) {
mergeColumnIndex = colRest._index;
}
}
if (mergeRowIndex > -1 && mergeColumnIndex > -1 && (rowspan || colspan)) {
rowspan = XEUtils.toNumber(rowspan) || 1;
colspan = XEUtils.toNumber(colspan) || 1;
if (rowspan > 1 || colspan > 1) {
const row = afterFullData[mergeRowIndex];
const column = visibleColumn[mergeColumnIndex];
let mergeItem = mergeBodyMaps[`${mergeRowIndex}:${mergeColumnIndex}`];
if (mergeItem) {
mergeItem.rowspan = rowspan;
mergeItem.colspan = colspan;
mergeItem._rowspan = rowspan;
mergeItem._colspan = colspan;
}
else {
mergeItem = {
row: mergeRowIndex,
col: mergeColumnIndex,
rowspan,
colspan,
_row: row,
_col: column,
_rowspan: rowspan,
_colspan: colspan
};
mergeBodyMaps[`${mergeRowIndex}:${mergeColumnIndex}`] = mergeItem;
mergeBodyList.push(mergeItem);
}
}
}
});
}
};
const removeBodyMerges = (merges) => {
const { mergeBodyList, fullColumnIdData, fullAllDataRowIdData, mergeBodyMaps } = internalData;
const rest = [];
if (merges) {
const { handleGetRowId } = createHandleGetRowId($xeTable);
if (!XEUtils.isArray(merges)) {
merges = [merges];
}
merges.forEach((item) => {
const { row: margeRow, col: margeCol } = item;
let mergeRowIndex = -1;
let mergeColumnIndex = -1;
if (XEUtils.isNumber(margeRow)) {
mergeRowIndex = margeRow;
}
else {
const rowid = margeRow ? handleGetRowId(margeRow) : null;
const rowRest = rowid ? fullAllDataRowIdData[rowid] : null;
if (rowRest) {
mergeRowIndex = rowRest._index;
}
}
if (XEUtils.isNumber(margeCol)) {
mergeColumnIndex = margeCol;
}
else {
const colid = margeCol ? margeCol.id : null;
const colRest = colid ? fullColumnIdData[colid] : null;
if (colRest) {
mergeColumnIndex = colRest._index;
}
}
const mcIndex = XEUtils.findIndexOf(mergeBodyList, item => item.row === mergeRowIndex && item.col === mergeColumnIndex);
if (mcIndex > -1) {
const rItems = mergeBodyList.splice(mcIndex, 1);
const item = rItems[0];
if (item) {
rest.push(rItems[0]);
if (mergeBodyMaps[`${mergeRowIndex}:${mergeColumnIndex}`]) {
delete mergeBodyMaps[`${mergeRowIndex}:${mergeColumnIndex}`];
}
}
}
});
}
return rest;
};
const handleUpdateMergeHeaderCells = (merges) => {
internalData.mergeHeaderList = [];
internalData.mergeHeaderMaps = {};
internalData.mergeHeaderCellMaps = {};
internalData.mergeHeaderRowMaps = {};
internalData.mergeBodyColMaps = {};
$xeTable.setMergeHeaderCells(merges);
};
const handleHeaderMerge = (merges) => {
const { showCustomHeader } = props;
const { footerTableData } = reactData;
const { mergeHeaderList, mergeHeaderMaps, fullColumnIdData } = internalData;
if (merges) {
const { visibleColumn } = internalData;
if (!XEUtils.isArray(merges)) {
merges = [merges];
}
merges.forEach((item) => {
let { row: margeRow, col: margeCol, rowspan, colspan } = item;
const mergeRowIndex = XEUtils.isNumber(margeRow) ? margeRow : -1;
let mergeColumnIndex = -1;
if (XEUtils.isNumber(margeCol)) {
mergeColumnIndex = margeCol;
}
else {
const colid = margeCol ? margeCol.id : null;
const colRest = colid ? fullColumnIdData[colid] : null;
if (colRest) {
mergeColumnIndex = colRest._index;
}
}
if (mergeRowIndex > -1 && mergeColumnIndex > -1 && (rowspan || colspan)) {
rowspan = XEUtils.toNumber(rowspan) || 1;
colspan = XEUtils.toNumber(colspan) || 1;
if (!showCustomHeader && rowspan > 1) {
errLog('vxe.error.notSupportProp', ['[table] show-custom-header=false', `rowspan=${rowspan}`, 'rowspan=1']);
return;
}
if (rowspan > 1 || colspan > 1) {
const row = footerTableData[mergeRowIndex];
const column = visibleColumn[mergeColumnIndex];
let mergeItem = mergeHeaderMaps[`${mergeRowIndex}:${mergeColumnIndex}`];
if (mergeItem) {
mergeItem.rowspan = rowspan;
mergeItem.colspan = colspan;
mergeItem._rowspan = rowspan;
mergeItem._colspan = colspan;
}
else {
mergeItem = {
row: mergeRowIndex,
col: mergeColumnIndex,
rowspan,
colspan,
_row: row,
_col: column,
_rowspan: rowspan,
_colspan: colspan
};
mergeHeaderMaps[`${mergeRowIndex}:${mergeColumnIndex}`] = mergeItem;
mergeHeaderList.push(mergeItem);
}
}
}
});
}
};
const removeHeaderMerges = (merges) => {
const { mergeHeaderList, fullColumnIdData, mergeHeaderMaps } = internalData;
const rest = [];
if (merges) {
if (!XEUtils.isArray(merges)) {
merges = [merges];
}
merges.forEach((item) => {
const { row: margeRow, col: margeCol } = item;
const mergeRowIndex = XEUtils.isNumber(margeRow) ? margeRow : -1;
let mergeColumnIndex = -1;
if (XEUtils.isNumber(margeCol)) {
mergeColumnIndex = margeCol;
}
else {
const colid = margeCol ? margeCol.id : null;
const colRest = colid ? fullColumnIdData[colid] : null;
if (colRest) {
mergeColumnIndex = colRest._index;
}
}
const mcIndex = XEUtils.findIndexOf(mergeHeaderList, item => item.row === mergeRowIndex && item.col === mergeColumnIndex);
if (mcIndex > -1) {
const rItems = mergeHeaderList.splice(mcIndex, 1);
const item = rItems[0];
if (item) {
rest.push(item);
if (mergeHeaderMaps[`${mergeRowIndex}:${mergeColumnIndex}`]) {
delete mergeHeaderMaps[`${mergeRowIndex}:${mergeColumnIndex}`];
}
}
}
});
}
return rest;
};
const handleUpdateMergeFooterCells = (merges) => {
internalData.mergeFooterList = [];
internalData.mergeFooterMaps = {};
internalData.mergeFooterCellMaps = {};
internalData.mergeFooterRowMaps = {};
internalData.mergeFooterColMaps = {};
$xeTable.setMergeFooterCells(merges);
};
const handleFooterMerge = (merges) => {
const { footerTableData } = reactData;
const { mergeFooterList, mergeFooterMaps, fullColumnIdData } = internalData;
if (merges) {
const { visibleColumn } = internalData;
if (!XEUtils.isArray(merges)) {
merges = [merges];
}
merges.forEach((item) => {
let { row: margeRow, col: margeCol, rowspan, colspan } = item;
const mergeRowIndex = XEUtils.isNumber(margeRow) ? margeRow : -1;
let mergeColumnIndex = -1;
if (XEUtils.isNumber(margeCol)) {
mergeColumnIndex = margeCol;
}
else {
const colid = margeCol ? margeCol.id : null;
const colRest = colid ? fullColumnIdData[colid] : null;
if (colRest) {
mergeColumnIndex = colRest._index;
}
}
if (mergeRowIndex > -1 && mergeColumnIndex > -1 && (rowspan || colspan)) {
rowspan = XEUtils.toNumber(rowspan) || 1;
colspan = XEUtils.toNumber(colspan) || 1;
if (rowspan > 1 || colspan > 1) {
const row = footerTableData[mergeRowIndex];
const column = visibleColumn[mergeColumnIndex];
let mergeItem = mergeFooterMaps[`${mergeRowIndex}:${mergeColumnIndex}`];
if (mergeItem) {
mergeItem.rowspan = rowspan;
mergeItem.colspan = colspan;
mergeItem._rowspan = rowspan;
mergeItem._colspan = colspan;
}
else {
mergeItem = {
row: mergeRowIndex,
col: mergeColumnIndex,
rowspan,
colspan,
_row: row,
_col: column,
_rowspan: rowspan,
_colspan: colspan
};
mergeFooterMaps[`${mergeRowIndex}:${mergeColumnIndex}`] = mergeItem;
mergeFooterList.push(mergeItem);
}
}
}
});
}
};
const removeFooterMerges = (merges) => {
const { mergeFooterList, fullColumnIdData, mergeFooterMaps } = internalData;
const rest = [];
if (merges) {
if (!XEUtils.isArray(merges)) {
merges = [merges];
}
merges.forEach((item) => {
const { row: margeRow, col: margeCol } = item;
const mergeRowIndex = XEUtils.isNumber(margeRow) ? margeRow : -1;
let mergeColumnIndex = -1;
if (XEUtils.isNumber(margeCol)) {
mergeColumnIndex = margeCol;
}
else {
const colid = margeCol ? margeCol.id : null;
const colRest = colid ? fullColumnIdData[colid] : null;
if (colRest) {
mergeColumnIndex = colRest._index;
}
}
const mcIndex = XEUtils.findIndexOf(mergeFooterList, item => item.row === mergeRowIndex && item.col === mergeColumnIndex);
if (mcIndex > -1) {
const rItems = mergeFooterList.splice(mcIndex, 1);
const item = rItems[0];
if (item) {
rest.push(item);
if (mergeFooterMaps[`${mergeRowIndex}:${mergeColumnIndex}`]) {
delete mergeFooterMaps[`${mergeRowIndex}:${mergeColumnIndex}`];
}
}
}
});
}
return rest;
};
const handleSortEvent = (evnt, sortConfs, isUpdate) => {
const { tableFullColumn } = internalData;
const sortOpts = computeSortOpts.value;
const { multiple, remote, orders } = sortOpts;
if (!XEUtils.isArray(sortConfs)) {
sortConfs = [sortConfs];
}
if (sortConfs && sortConfs.length) {
const orderActiveMaps = {};
if (!multiple) {
sortConfs = [sortConfs[0]];
tableFullColumn.forEach((column) => {
if (column.order) {
orderActiveMaps[column.id] = column;
}
});
}
const sortColMpps = {};
let firstColumn = null;
sortConfs.forEach((confs, index) => {
let { field, order } = confs;
let column = field;
if (XEUtils.isString(field)) {
column = $xeTable.getColumnByField(field);
}
if (!firstColumn) {
firstColumn = column;
}
if (column && column.sortable) {
if (orders && orders.indexOf(order) === -1) {
order = getNextSortOrder(column);
}
if (column.order !== order) {
column.order = order;
}
column.sortTime = Date.now() + index;
sortColMpps[column.id] = column;
}
});
if (!multiple) {
XEUtils.each(orderActiveMaps, (oaCol, oaId) => {
if (!sortColMpps[oaId]) {
oaCol.order = null;
}
});
}
if (isUpdate) {
if (!remote) {
$xeTable.handleTableData(true);
}
}
if (evnt) {
$xeTable.handleColumnSortEvent(evnt, firstColumn);
}
return nextTick().then(() => {
updateRowOffsetTop();
$xeTable.updateCellAreas();
return updateStyle();
});
}
return nextTick();
};
const clearAllSort = () => {
const { tableFullColumn } = internalData;
tableFullColumn.forEach((column) => {
column.order = null;
});
};
const calcTableHeight = (key) => {
const { editConfig, editRules } = props;
const { parentHeight, tableColumn } = reactData;
let val = props[key];
if (key === 'minHeight') {
const defMinHeight = getConfig().table.minHeight;
if (XEUtils.eqNull(val)) {
if (eqEmptyValue(defMinHeight)) {
if (!tableColumn.length) {
// 如果全部列被隐藏
val = 40;
}
else if (editRules && isEnableConf(editConfig)) {
// 编辑模式默认最小高度
val = 144;
}
}
else {
val = defMinHeight;
}
}
}
let num = 0;
if (val) {
if (val === '100%' || val === 'auto') {
num = parentHeight;
}
else {
const excludeHeight = $xeTable.getExcludeHeight();
if (isScale(val)) {
num = Math.floor((XEUtils.toInteger(val) || 1) / 100 * parentHeight);
}
else {
num = XEUtils.toNumber(val);
}
num = Math.max(40, num - excludeHeight);
}
}
return num;
};
const handleCustomRestore = (storeData) => {
const { aggregateConfig, rowGroupConfig } = props;
const { collectColumn } = internalData;
const { isCustomAlign, isCustomHeaderAlign, isCustomFooterAlign, isCustomResizable, isCustomVisible, isCustomFixed, isCustomSort, isCustomAggGroup, isCustomAggFunc, isCustomPager } = handleCustomStoreConfig($xeTable);
let { alignData, headerAlignData, footerAlignData, resizableData, sortData, visibleData, fixedData, aggGroupData, aggFuncData, pagerData } = storeData;
// 处理还原
if ((isCustomAlign && alignData) ||
(isCustomHeaderAlign && headerAlignData) ||
(isCustomFooterAlign && footerAlignData) ||
(isCustomResizable && resizableData) ||
(isCustomSort && sortData) ||
(isCustomVisible && visibleData) ||
(isCustomFixed && fixedData) ||
(isCustomAggGroup && aggGroupData) ||
(isCustomAggFunc && aggFuncData) ||
(isCustomPager && pagerData && $xeGGWrapper)) {
const sortColMaps = {};
if (isCustomSort && sortData) {
// 转换兼容老版本数据,即将废弃兼容
if (!XEUtils.isArray(sortData)) {
const sortRests = [];
XEUtils.each(sortData, (index, colKey) => {
sortRests.push({ key: colKey, index });
});
sortData = XEUtils.orderBy(sortRests, { field: 'index', order: 'asc' }).map(item => ({ k: item.key }));
}
let colNum = 1;
XEUtils.eachTree(sortData, (sObj, index, sOjs, path, pSObj) => {
sortColMaps[sObj.k] = {
key: sObj.k,
sNum: colNum++,
pKey: pSObj ? pSObj.k : null
};
}, { children: 'c' });
}
const colKeyMaps = {};
const allCols = [];
const aggGroupConfs = [];
XEUtils.eachTree(collectColumn, (column, index, items, path, parentColumn) => {
const colKey = column.getKey();
// 支持一级
if (!parentColumn) {
if (isCustomFixed && fixedData && fixedData[colKey] !== undefined) {
column.fixed = fixedData[colKey];
}
}
if (isCustomResizable && resizableData && XEUtils.isNumber(resizableData[colKey])) {
column.resizeWidth = resizableData[colKey];
}
if (isCustomVisible && visibleData && XEUtils.isBoolean(visibleData[colKey])) {
column.visible = visibleData[colKey];
}
if (isCustomAggFunc && aggFuncData && (aggregateConfig || rowGroupConfig) && aggFuncData[colKey]) {
column.aggFunc = aggFuncData[colKey];
}
if (isCustomAggGroup && aggGroupData && aggGroupData[colKey]) {
aggGroupConfs.push({ field: column.field });
}
colKeyMaps[colKey] = column;
allCols.push(column);
});
if ((aggregateConfig || rowGroupConfig) && aggGroupConfs.length) {
const groupRest = handleGroupData(internalData.tableFullData, aggGroupConfs);
internalData.tableFullTreeData = [];
internalData.tableFullGroupData = groupRest.treeData;
reactData.isRowGroupStatus = true;
reactData.rowGroupList = aggGroupConfs;
$xeTable.cacheRowMap(false);
}
// 如果自定义了顺序
if (isCustomSort && sortData) {
allCols.forEach(column => {
const colKey = column.getKey();
const scItem = sortColMaps[colKey];
if (scItem) {
const parentColumn = scItem.pKey ? colKeyMaps[scItem.pKey] : null;
column.parentId = parentColumn ? parentColumn.id : null;
column.renderSortNumber = scItem.sNum;
}
});
const newCollectCols = XEUtils.toArrayTree(XEUtils.orderBy(allCols, 'renderSortNumber'), { key: 'id', parentKey: 'parentId', children: 'children' });
internalData.collectColumn = newCollectCols;
internalData.tableFullColumn = getColumnList(newCollectCols);
reactData.updateColFlag++;
}
reactData.isCustomStatus = true;
}
else {
reactData.isCustomStatus = false;
}
};
/**
* 还原自定义列操作状态
*/
const restoreCustomStorage = () => {
const { customConfig } = props;
const tableId = computeTableId.value;
const customOpts = computeCustomOpts.value;
const { storage, restoreStore } = customOpts;
const { isCustomAlign, isCustomHeaderAlign, isCustomFooterAlign, isCustomResizable, isCustomVisible, isCustomFixed, isCustomSort, isCustomAggGroup, isCustomAggFunc } = handleCustomStoreConfig($xeTable);
if (storage &&
(customConfig ? isEnableConf(customOpts) : customOpts.enabled) &&
(isCustomAlign ||
isCustomHeaderAlign ||
isCustomFooterAlign ||
isCustomResizable ||
isCustomVisible ||
isCustomFixed ||
isCustomSort ||
isCustomAggGroup ||
isCustomAggFunc)) {
if (!tableId) {
errLog('vxe.error.reqProp', ['id']);
return;
}
const storeData = getCustomStorageMap(tableId);
if (restoreStore) {
return Promise.resolve(restoreStore({ $table: $xeTable, id: tableId, type: 'restore', storeData })).then(storeData => {
if (!storeData) {
return;
}
return handleCustomRestore(storeData);
}).catch(e => e);
}
else {
return handleCustomRestore(storeData);
}
}
};
const updateColumnAllOverflow = () => {
const { showOverflow } = props;
const { isGroup } = reactData;
const { fullAllDataRowIdData, tableFullColumn, collectColumn } = internalData;
let isAllOverflow = !!showOverflow;
const handleFunc = (column) => {
if (isAllOverflow && column.showOverflow === false) {
isAllOverflow = false;
}
};
if (isGroup) {
XEUtils.eachTree(collectColumn, handleFunc);
}
else {
tableFullColumn.forEach(handleFunc);
}
XEUtils.each(fullAllDataRowIdData, (rowRest) => {
rowRest.height = 0;
});
reactData.isAllOverflow = isAllOverflow;
};
/**
* 更新数据列的 Map
* 牺牲数据组装的耗时,用来换取使用过程中的流畅
*/
const cacheColumnMap = () => {
const { treeConfig, showOverflow } = props;
const { tableFullColumn, collectColumn } = internalData;
const fullColIdData = internalData.fullColumnIdData = {};
const fullColFieldData = internalData.fullColumnFieldData = {};
const mouseOpts = computeMouseOpts.value;
const expandOpts = computeExpandOpts.value;
const columnOpts = computeColumnOpts.value;
const columnDragOpts = computeColumnDragOpts.value;
const virtualYOpts = computeVirtualYOpts.value;
const { isCrossDrag, isSelfToChildDrag } = columnDragOpts;
const customOpts = computeCustomOpts.value;
const treeOpts = computeTreeOpts.value;
const { storage } = customOpts;
const rowOpts = computeRowOpts.value;
const isGroup = collectColumn.some(hasChildrenList);
let isAllOverflow = !!showOverflow;
let rowGroupColumn;
let expandColumn;
let treeNodeColumn;
let checkboxColumn;
let radioColumn;
let htmlColumn;
let hasFixed;
const handleFunc = (column, index, items, path, parentColumn) => {
const { id: colid, field, fixed, type, treeNode, rowGroupNode } = column;
const rest = { $index: -1, _index: -1, column, colid, index, items, parent: parentColumn || null, width: 0, oLeft: 0 };
if (field) {
if (fullColFieldData[field]) {
errLog('vxe.error.colRepet', ['field', field]);
}
fullColFieldData[field] = rest;
}
else {
if (storage && !type) {
errLog('vxe.error.reqSupportProp', ['storage', `[${type ? `type=${type}` : `title=${column.getTitle()}`}]field=?`]);
}
if (columnOpts.drag && (isCrossDrag || isSelfToChildDrag)) {
errLog('vxe.error.reqSupportProp', ['column-drag-config.isCrossDrag | column-drag-config.isSelfToChildDrag', `${column.getTitle() || type || ''} -> field=?`]);
}
}
if (!hasFixed && fixed) {
hasFixed = fixed;
}
if (!htmlColumn && type === 'html') {
htmlColumn = column;
}
if (treeNode) {
if (treeNodeColumn) {
warnLog('vxe.error.colRepet', ['tree-node', treeNode]);
}
if (!treeNodeColumn) {
treeNodeColumn = column;
}
}
if (rowGroupNode) {
if (treeNodeColumn) {
warnLog('vxe.error.colRepet', ['row-group-node', rowGroupNode]);
}
if (!rowGroupColumn) {
rowGroupColumn = column;
}
}
if (type === 'expand') {
if (expandColumn) {
warnLog('vxe.error.colRepet', ['type', type]);
}
if (!expandColumn) {
expandColumn = column;
}
}
if (type === 'checkbox') {
if (checkboxColumn) {
warnLog('vxe.error.colRepet', ['type', type]);
}
if (!checkboxColumn) {
checkboxColumn = column;
}
}
else if (type === 'radio') {
if (radioColumn) {
warnLog('vxe.error.colRepet', ['type', type]);
}
if (!radioColumn) {
radioColumn = column;
}
}
if (isAllOverflow && column.showOverflow === false) {
isAllOverflow = false;
}
if (fullColIdData[colid]) {
errLog('vxe.error.colRepet', ['colId', colid]);
}
fullColIdData[colid] = rest;
};
if (isGroup) {
XEUtils.eachTree(collectColumn, (column, index, items, path, parentColumn, nodes) => {
column.level = nodes.length;
handleFunc(column, index, items, path, parentColumn);
});
}
else {
tableFullColumn.forEach(handleFunc);
}
if (expandColumn) {
if (expandOpts.mode !== 'fixed' && virtualYOpts.enabled) {
warnLog('vxe.error.notConflictProp', ['column.type="expand', 'virtual-y-config.enabled=false']);
}
if ((expandOpts.mode !== 'fixed') && mouseOpts.area) {
errLog('vxe.error.errConflicts', ['mouse-config.area', 'column.type=expand']);
}
if (expandOpts.mode !== 'inside' && (treeConfig && !treeOpts.transform)) {
errLog('vxe.error.notConflictProp', ['tree-config.transform=false', 'expand-config.mode=inside']);
}
// if (props.spanMethod) {
// warnLog('vxe.error.notSupportProp', ['column.type=expand', 'span-method', 'span-method=null'])
// }
}
if (htmlColumn) {
if (!columnOpts.useKey) {
errLog('vxe.error.notSupportProp', ['column.type=html', 'column-config.useKey=false', 'column-config.useKey=true']);
}
if (!rowOpts.useKey) {
errLog('vxe.error.notSupportProp', ['column.type=html', 'row-config.useKey=false', 'row-config.useKey=true']);
}
}
reactData.isGroup = isGroup;
reactData.rowGroupColumn = rowGroupColumn;
reactData.treeNodeColumn = treeNodeColumn;
reactData.expandColumn = expandColumn;
reactData.checkboxColumn = checkboxColumn;
reactData.radioColumn = radioColumn;
reactData.isAllOverflow = isAllOverflow;
};
const updateHeight = () => {
internalData.customHeight = calcTableHeight('height');
internalData.customMinHeight = calcTableHeight('minHeight');
internalData.customMaxHeight = calcTableHeight('maxHeight');
// 如果启用虚拟滚动,纠正高度
if (reactData.scrollYLoad && !(internalData.customHeight || internalData.customMinHeight || internalData.customMaxHeight)) {
internalData.customHeight = 300;
}
};
/**
* 计算自适应列宽
*/
const calcColumnAutoWidth = (column, wrapperEl) => {
const { scrollYLoad } = reactData;
const columnOpts = computeColumnOpts.value;
const { autoOptions } = columnOpts;
const { isCalcHeader, isCalcBody, isCalcFooter } = autoOptions || {};
const querySelections = [];
if (isCalcHeader) {
querySelections.push(`.vxe-header-cell--wrapper[colid="${column.id}"]`);
}
if (isCalcBody) {
querySelections.push(`.vxe-body-cell--wrapper[colid="${column.id}"]`);
}
if (isCalcFooter) {
querySelections.push(`.vxe-footer-cell--wrapper[colid="${column.id}"]`);
}
const cellElemList = querySelections.length ? wrapperEl.querySelectorAll(querySelections.join(',')) : [];
let leftRightPadding = 0;
const firstCellEl = cellElemList[0];
if (firstCellEl && firstCellEl.parentElement) {
const cellStyle = getComputedStyle(firstCellEl.parentElement);
leftRightPadding = Math.ceil(XEUtils.toNumber(cellStyle.paddingLeft) + XEUtils.toNumber(cellStyle.paddingRight));
}
let colWidth = (scrollYLoad ? column.renderAutoWidth : 0) - leftRightPadding;
for (let i = 0; i < cellElemList.length; i++) {
const celEl = cellElemList[i];
colWidth = Math.max(colWidth, celEl ? Math.ceil(celEl.scrollWidth) + 4 : 0);
}
return colWidth + leftRightPadding;
};
/**
* 自适应列宽
*/
const calcCellWidth = () => {
const autoWidthColumnList = computeAutoWidthColumnList.value;
const { fullColumnIdData } = internalData;
const el = refElem.value;
if (el && autoWidthColumnList.length) {
el.setAttribute('data-calc-col', 'Y');
autoWidthColumnList.forEach(column => {
const colid = column.id;
const colRest = fullColumnIdData[colid];
const colWidth = calcColumnAutoWidth(column, el);
if (colRest) {
colRest.width = Math.max(colWidth, colRest.width);
}
column.renderAutoWidth = colWidth;
});
$xeTable.analyColumnWidth();
el.removeAttribute('data-calc-col');
}
};
/**
* 列宽算法,计算单元格列宽,动态分配可用剩余空间
* 支持 px、%、固定 混合分配
* 支持动态列表调整分配
* 支持自动分配偏移量
* 支持 width=60 width=60px width=10% min-width=60 min-width=60px min-width=10%
*/
const autoCellWidth = () => {
const { elemStore } = internalData;
const bodyWrapperElem = getRefElem(elemStore['main-body-wrapper']);
if (!bodyWrapperElem) {
return;
}
const yHandleEl = refScrollYHandleElem.value;
if (!yHandleEl) {
return;
}
const xHandleEl = refScrollXHandleElem.value;
if (!xHandleEl) {
return;
}
const columnOpts = computeColumnOpts.value;
let tWidth = 0;
const minCellWidth = 40; // 列宽最少限制 40px
const bodyWidth = bodyWrapperElem.clientWidth;
let remainWidth = bodyWidth;
let meanWidth = remainWidth / 100;
const { fit } = props;
const { columnStore } = reactData;
const { resizeList, pxMinList, autoMinList, pxList, scaleList, scaleMinList, autoList, remainList } = columnStore;
const parseColumnMaxWidth = (column) => {
const maxWidth = column.maxWidth || columnOpts.maxWidth;
if (maxWidth && maxWidth !== 'auto') {
if (isScale(maxWidth)) {
return Math.floor(XEUtils.toInteger(maxWidth) * meanWidth);
}
return XEUtils.toInteger(maxWidth);
}
return 0;
};
// 最小宽
pxMinList.forEach((column) => {
let miWidth = XEUtils.toInteger(column.minWidth);
const mxWidth = parseColumnMaxWidth(column);
if (mxWidth) {
miWidth = Math.min(miWidth, mxWidth);
}
tWidth += miWidth;
column.renderWidth = miWidth;
});
// 最小自适应
autoMinList.forEach((column) => {
let caWidth = Math.max(60, XEUtils.toInteger(column.renderAutoWidth));
const mxWidth = parseColumnMaxWidth(column);
if (mxWidth) {
caWidth = Math.min(caWidth, mxWidth);
}
tWidth += caWidth;
column.renderWidth = caWidth;
});
// 最小百分比
scaleMinList.forEach((column) => {
let smWidth = Math.floor(XEUtils.toInteger(column.minWidth) * meanWidth);
const mxWidth = parseColumnMaxWidth(column);
if (mxWidth) {
smWidth = Math.min(smWidth, mxWidth);
}
tWidth += smWidth;
column.renderWidth = smWidth;
});
// 固定百分比
scaleList.forEach((column) => {
let sfWidth = Math.floor(XEUtils.toInteger(column.width) * meanWidth);
const mxWidth = parseColumnMaxWidth(column);
if (mxWidth) {
sfWidth = Math.min(sfWidth, mxWidth);
}
tWidth += sfWidth;
column.renderWidth = sfWidth;
});
// 固定宽
pxList.forEach((column) => {
let pWidth = XEUtils.toInteger(column.width);
const mxWidth = parseColumnMaxWidth(column);
if (mxWidth) {
pWidth = Math.min(pWidth, mxWidth);
}
tWidth += pWidth;
column.renderWidth = pWidth;
});
// 自适应宽
autoList.forEach((column) => {
let aWidth = Math.max(60, XEUtils.toInteger(column.renderAutoWidth));
const mxWidth = parseColumnMaxWidth(column);
if (mxWidth) {
aWidth = Math.min(aWidth, mxWidth);
}
tWidth += aWidth;
column.renderWidth = aWidth;
});
// 调整了列宽
resizeList.forEach((column) => {
const reWidth = XEUtils.toInteger(column.resizeWidth);
tWidth += reWidth;
column.renderWidth = reWidth;
});
const zoomColumnList = scaleMinList.concat(pxMinList).concat(autoMinList).filter(column => !parseColumnMaxWidth(column));
remainWidth -= tWidth;
meanWidth = remainWidth > 0 ? Math.floor(remainWidth / (zoomColumnList.length + remainList.length)) : 0;
if (fit) {
if (remainWidth > 0) {
zoomColumnList.forEach((column) => {
tWidth += meanWidth;
column.renderWidth += meanWidth;
});
}
}
else {
meanWidth = minCellWidth;
}
// 剩余均分
remainList.forEach((column) => {
const width = Math.max(meanWidth, minCellWidth);
column.renderWidth = width;
tWidth += width;
});
if (fit) {
/**
* 偏移量算法
* 如果所有列足够放的情况下,从最后动态列开始分配
* 排除已设置 max-width
*/
const dynamicList = scaleList.concat(scaleMinList).concat(pxMinList).concat(autoMinList).concat(remainList).filter(column => !parseColumnMaxWidth(column));
let dynamicSize = dynamicList.length - 1;
if (dynamicSize > 0) {
let i = bodyWidth - tWidth;
if (i > 0) {
while (i > 0 && dynamicSize >= 0) {
i--;
dynamicList[dynamicSize--].renderWidth++;
}
tWidth = bodyWidth;
}
}
}
reactData.scrollXWidth = tWidth;
reactData.resizeWidthFlag++;
updateColumnOffsetLeft();
updateHeight();
};
/**
* 计算自适应行高
*/
const calcCellAutoHeight = (rowid, rowRest, wrapperEl) => {
const { fullCellHeightMaps } = internalData;
let chRest = fullCellHeightMaps[rowid];
if (!chRest) {
chRest = {};
fullCellHeightMaps[rowid] = chRest;
}
const wrapperElemList = wrapperEl.querySelectorAll(`.vxe-cell--wrapper[rowid="${rowRest.rowid}"]`);
let firstCellStyle = null;
let topBottomPadding = 0;
let changeCH = false;
for (let i = 0; i < wrapperElemList.length; i++) {
const wrapperElem = wrapperElemList[i];
const cellElem = wrapperElem.parentElement;
const cellStyle = cellElem.style;
const orHeight = cellStyle.height;
const colid = wrapperElem.getAttribute('colid') || '';
cellStyle.height = '';
if (!firstCellStyle) {
firstCellStyle = getComputedStyle(cellElem);
topBottomPadding = firstCellStyle ? Math.ceil(XEUtils.toNumber(firstCellStyle.paddingTop) + XEUtils.toNumber(firstCellStyle.paddingBottom)) : 0;
}
const cellHeight = wrapperElem ? wrapperElem.clientHeight : 0;
const colHeight = Math.ceil(cellHeight + topBottomPadding);
if (chRest[colid] !== colHeight) {
changeCH = true;
chRest[colid] = colHeight;
}
cellStyle.height = orHeight;
}
const cellMaxHeight = getRowMaxHeight(chRest, changeCH);
return cellMaxHeight;
};
/**
* 自适应行高
*/
const calcCellHeight = () => {
const { treeConfig } = props;
const { tableData, isAllOverflow, scrollYLoad, scrollXLoad } = reactData;
const { fullAllDataRowIdData } = internalData;
const el = refElem.value;
if (!el || !el.clientWidth) {
return;
}
const treeOpts = computeTreeOpts.value;
const defaultRowHeight = computeDefaultRowHeight.value;
if (!isAllOverflow && (scrollYLoad || scrollXLoad || (treeConfig && treeOpts.showLine))) {
const { handleGetRowId } = createHandleGetRowId($xeTable);
el.setAttribute('data-calc-row', 'Y');
tableData.forEach(row => {
const rowid = handleGetRowId(row);
const rowRest = fullAllDataRowIdData[rowid];
if (rowRest) {
const reHeight = calcCellAutoHeight(rowid, rowRest, el);
rowRest.height = Math.max(defaultRowHeight, reHeight);
}
el.removeAttribute('data-calc-row');
});
reactData.calcCellHeightFlag++;
}
};
const getOrderField = (column) => {
const { isRowGroupStatus } = reactData;
const { sortBy, sortType, aggFunc } = column;
return isRowGroupStatus && aggFunc
? (row) => {
if (row.isAggregate) {
const aggData = row.aggData;
const currAggData = aggData ? aggData[column.field] : null;
return currAggData ? currAggData.value : null;
}
let cellValue;
if (sortBy) {
cellValue = XEUtils.isFunction(sortBy) ? sortBy({ row, column }) : XEUtils.get(row, sortBy);
}
else {
cellValue = $xeTable.getCellLabel(row, column);
}
if (!sortType || sortType === 'auto') {
return eqEmptyValue(cellValue) || isNaN(cellValue) ? cellValue : XEUtils.toNumber(cellValue);
}
else if (sortType === 'number') {
return XEUtils.toNumber(cellValue);
}
else if (sortType === 'string') {
return XEUtils.toValueString(cellValue);
}
return cellValue;
}
: (row) => {
let cellValue;
if (sortBy) {
cellValue = XEUtils.isFunction(sortBy) ? sortBy({ row, column }) : XEUtils.get(row, sortBy);
}
else {
cellValue = $xeTable.getCellLabel(row, column);
}
if (!sortType || sortType === 'auto') {
return eqEmptyValue(cellValue) || isNaN(cellValue) ? cellValue : XEUtils.toNumber(cellValue);
}
else if (sortType === 'number') {
return XEUtils.toNumber(cellValue);
}
else if (sortType === 'string') {
return XEUtils.toValueString(cellValue);
}
return cellValue;
};
};
const updateAfterTreeIndex = () => {
const { fullDataRowIdData, fullAllDataRowIdData, afterFullData, afterTreeFullData } = internalData;
const treeOpts = computeTreeOpts.value;
const { transform, mapChildrenField } = treeOpts;
const childrenField = treeOpts.children || treeOpts.childrenField;
const fullMaps = {};
let rowNum = 0;
const { handleGetRowId } = createHandleGetRowId($xeTable);
XEUtils.eachTree(afterTreeFullData, (row, index, items, path, parentRow) => {
const rowid = handleGetRowId(row);
const rowRest = fullAllDataRowIdData[rowid];
const seq = path.map((num, i) => i % 2 === 0 ? (Number(num) + 1) : '.').join('');
if (rowRest) {
rowRest.seq = seq;
rowRest._seq = rowNum;
rowRest.treeIndex = index;
rowRest._index = rowNum;
rowRest._tIndex = rowNum;
}
else {
const rest = { row, rowid, _seq: rowNum, seq, index, $index: -1, _index: rowNum, treeIndex: index, _tIndex: rowNum, items, parent: parentRow, level: 0, height: 0, resizeHeight: 0, oTop: 0, expandHeight: 0 };
fullAllDataRowIdData[rowid] = rest;
fullDataRowIdData[rowid] = rest;
}
rowNum++;
fullMaps[rowid] = row;
}, { children: transform ? mapChildrenField : childrenField });
if (transform) {
afterFullData.forEach((row, index) => {
const rowid = handleGetRowId(row);
const rowRest = fullAllDataRowIdData[rowid];
if (rowRest) {
rowRest._index = index;
}
});
}
internalData.afterFullRowMaps = fullMaps;
};
const updateAfterListIndex = () => {
const { afterFullData, fullDataRowIdData, fullAllDataRowIdData } = internalData;
const { handleGetRowId } = createHandleGetRowId($xeTable);
const fullMaps = {};
let rowNum = 0;
afterFullData.forEach((row, index) => {
const rowid = handleGetRowId(row);
const rowRest = fullAllDataRowIdData[rowid];
const seq = index + 1;
if (rowRest) {
rowRest.seq = seq;
rowRest._seq = rowNum;
rowRest._index = index;
}
else {
const rest = { row, rowid, _seq: rowNum, seq, index: -1, $index: -1, _index: index, treeIndex: -1, _tIndex: -1, items: [], parent: null, level: 0, height: 0, resizeHeight: 0, oTop: 0, expandHeight: 0 };
fullAllDataRowIdData[rowid] = rest;
fullDataRowIdData[rowid] = rest;
}
rowNum++;
fullMaps[rowid] = row;
});
internalData.afterFullRowMaps = fullMaps;
};
/**
* 预编译
* 对渲染中的数据提前解析序号及索引。牺牲提前编译耗时换取渲染中额外损耗,使运行时更加流畅
*/
const updateAfterDataIndex = () => {
const { treeConfig } = props;
if (treeConfig) {
updateAfterTreeIndex();
}
else {
updateAfterListIndex();
}
};
/**
* 如果为虚拟树、行分组、则将树结构拍平
* @returns
*/
const handleVirtualTreeToList = () => {
const { treeConfig } = props;
const { isRowGroupStatus } = reactData;
const { fullAllDataRowIdData, treeExpandedMaps, rowGroupExpandedMaps } = internalData;
const aggregateOpts = computeAggregateOpts.value;
const treeOpts = computeTreeOpts.value;
const { handleGetRowId } = createHandleGetRowId($xeTable);
const fullData = [];
const expandMaps = {};
if (treeConfig && treeOpts.transform) {
const childrenField = treeOpts.children || treeOpts.childrenField;
XEUtils.eachTree(internalData.afterTreeFullData, (row, index, items, path, parentRow) => {
const rowid = handleGetRowId(row);
const parentRowid = handleGetRowId(parentRow);
if (!parentRow || (expandMaps[parentRowid] && treeExpandedMaps[parentRowid])) {
const rowRest = fullAllDataRowIdData[rowid];
if (rowRest) {
rowRest._index = fullData.length;
}
expandMaps[rowid] = 1;
fullData.push(row);
}
}, { children: childrenField });
internalData.afterFullData = fullData;
updateScrollYStatus(fullData);
return fullData;
}
else if (isRowGroupStatus) {
const { childrenField } = aggregateOpts;
XEUtils.eachTree(internalData.afterGroupFullData, (row, index, items, path, parentRow) => {
const rowid = handleGetRowId(row);
const parentRowid = handleGetRowId(parentRow);
if (!parentRow || (expandMaps[parentRowid] && rowGroupExpandedMaps[parentRowid])) {
const rowRest = fullAllDataRowIdData[rowid];
if (rowRest) {
rowRest._index = fullData.length;
}
expandMaps[rowid] = 1;
fullData.push(row);
}
}, { children: childrenField });
internalData.afterFullData = fullData;
updateScrollYStatus(fullData);
return fullData;
}
return internalData.afterFullData;
};
/**
* 编译处理后全量的表格数据
* 如果存在筛选条件,继续处理
*/
const updateAfterFullData = () => {
const { treeConfig } = props;
const { isRowGroupStatus } = reactData;
const { tableFullColumn, tableFullData, tableFullTreeData, tableFullGroupData } = internalData;
const filterOpts = computeFilterOpts.value;
const sortOpts = computeSortOpts.value;
const aggregateOpts = computeAggregateOpts.value;
const treeOpts = computeTreeOpts.value;
const childrenField = treeOpts.children || treeOpts.childrenField;
const { transform, rowField, parentField, mapChildrenField } = treeOpts;
const { isEvery, remote: allRemoteFilter, filterMethod: allFilterMethod, isDeep: isFilterDeep } = filterOpts;
const { remote: allRemoteSort, sortMethod: allSortMethod, multiple: sortMultiple, chronological, isDeep: isSortDeep } = sortOpts;
let tableData = [];
let tableTree = [];
// 处理数据
if (!allRemoteFilter || !allRemoteSort) {
const filterColumns = [];
let orderColumns = [];
tableFullColumn.forEach((column) => {
const { field, sortable, order, filters } = column;
if (!allRemoteFilter && filters && filters.length) {
const valueList = [];
const itemList = [];
filters.forEach((item) => {
if (item.checked) {
itemList.push(item);
valueList.push(item.value);
}
});
if (itemList.length) {
filterColumns.push({ column, valueList, itemList });
}
}
if (!allRemoteSort && sortable && order) {
orderColumns.push({ column, field, property: field, order: order, sortTime: column.sortTime });
}
});
if (sortMultiple && chronological && orderColumns.length > 1) {
orderColumns = XEUtils.orderBy(orderColumns, 'sortTime');
}
// 处理筛选
// 支持单列、多列、组合筛选
if (!allRemoteFilter && filterColumns.length) {
const handleFilter = (row) => {
return filterColumns.every(({ column, valueList, itemList }) => {
const { filterMethod, filterRender } = column;
const compConf = isEnableConf(filterRender) ? renderer.get(filterRender.name) : null;
const compFilterMethod = compConf ? (compConf.tableFilterMethod || compConf.filterMethod) : null;
const tdFilterMethod = compConf ? (compConf.tableFilterDefaultMethod || compConf.defaultTableFilterMethod || compConf.defaultFilterMethod) : null;
const cellValue = getCellValue(row, column);
if (filterMethod) {
return itemList.some((item) => filterMethod({ value: item.value, option: item, cellValue, row, column, $table: $xeTable }));
}
else if (compFilterMethod) {
return itemList.some((item) => compFilterMethod({ value: item.value, option: item, cellValue, row, column, $table: $xeTable }));
}
else if (allFilterMethod) {
return allFilterMethod({ $table: $xeTable, options: itemList, values: valueList, cellValue, row, column });
}
else if (tdFilterMethod) {
return itemList.some((item) => tdFilterMethod({ value: item.value, option: item, cellValue, row, column, $table: $xeTable }));
}
return valueList.indexOf(XEUtils.get(row, column.field)) > -1;
});
};
if (isRowGroupStatus) {
// 行分组
tableTree = XEUtils.searchTree(tableFullGroupData, handleFilter, {
original: true,
isEvery: true,
children: aggregateOpts.mapChildrenField,
mapChildren: aggregateOpts.childrenField
});
tableData = tableTree;
}
else if (treeConfig && transform && isFilterDeep !== false) {
// 筛选虚拟树
tableTree = XEUtils.searchTree(tableFullTreeData, handleFilter, {
original: true,
isEvery,
children: mapChildrenField,
mapChildren: childrenField
});
tableData = tableTree;
}
else {
tableData = treeConfig ? tableFullTreeData.filter(handleFilter) : tableFullData.filter(handleFilter);
tableTree = tableData;
}
}
else {
if (isRowGroupStatus) {
// 还原行分组
tableTree = XEUtils.searchTree(tableFullGroupData, () => true, {
original: true,
isEvery: true,
children: aggregateOpts.mapChildrenField,
mapChildren: aggregateOpts.childrenField
});
tableData = tableTree;
}
else if (treeConfig && transform && isFilterDeep !== false) {
// 还原虚拟树
tableTree = XEUtils.searchTree(tableFullTreeData, () => true, {
original: true,
isEvery,
children: mapChildrenField,
mapChildren: childrenField
});
tableData = tableTree;
}
else {
tableData = treeConfig ? tableFullTreeData.slice(0) : tableFullData.slice(0);
tableTree = tableData;
}
}
// 处理排序
// 支持单列、多列、组合排序
if (!allRemoteSort && orderColumns.length) {
if (isRowGroupStatus) {
// 行分组的排序
if (allSortMethod) {
const sortRests = allSortMethod({ data: tableTree, sortList: orderColumns, $table: $xeTable });
tableTree = XEUtils.isArray(sortRests) ? sortRests : tableTree;
}
else {
const treeList = XEUtils.toTreeArray(tableTree, {
key: aggregateOpts.rowField,
parentKey: aggregateOpts.parentField,
children: aggregateOpts.mapChildrenField
});
tableTree = XEUtils.toArrayTree(XEUtils.orderBy(treeList, orderColumns.map(({ column, order }) => [getOrderField(column), order])), {
key: aggregateOpts.rowField,
parentKey: aggregateOpts.parentField,
children: aggregateOpts.childrenField,
mapChildren: aggregateOpts.mapChildrenField
});
}
tableData = tableTree;
}
else if (treeConfig && transform && isSortDeep !== false) {
// 虚拟树的排序
if (allSortMethod) {
const sortRests = allSortMethod({ data: tableTree, sortList: orderColumns, $table: $xeTable });
tableTree = XEUtils.isArray(sortRests) ? sortRests : tableTree;
}
else {
const treeList = XEUtils.toTreeArray(tableTree, {
children: mapChildrenField
});
tableTree = XEUtils.toArrayTree(XEUtils.orderBy(treeList, orderColumns.map(({ column, order }) => [getOrderField(column), order])), {
key: rowField,
parentKey: parentField,
children: childrenField,
mapChildren: mapChildrenField
});
}
tableData = tableTree;
}
else {
if (allSortMethod) {
const sortRests = allSortMethod({ data: tableData, sortList: orderColumns, $table: $xeTable });
tableData = XEUtils.isArray(sortRests) ? sortRests : tableData;
}
else {
tableData = XEUtils.orderBy(tableData, orderColumns.map(({ column, order }) => [getOrderField(column), order]));
}
tableTree = tableData;
}
}
}
else {
if (isRowGroupStatus) {
// 还原行分组
// 还原虚拟树
tableTree = XEUtils.searchTree(tableFullGroupData, () => true, {
original: true,
isEvery: true,
children: aggregateOpts.mapChildrenField,
mapChildren: aggregateOpts.childrenField
});
tableData = tableTree;
}
else if (treeConfig && transform && isSortDeep !== false) {
// 还原虚拟树
tableTree = XEUtils.searchTree(tableFullTreeData, () => true, {
original: true,
isEvery,
children: mapChildrenField,
mapChildren: childrenField
});
tableData = tableTree;
}
else {
tableData = treeConfig ? tableFullTreeData.slice(0) : tableFullData.slice(0);
tableTree = tableData;
}
}
internalData.afterFullData = tableData;
internalData.afterTreeFullData = tableTree;
internalData.afterGroupFullData = tableTree;
updateAfterDataIndex();
};
const updateStyle = () => {
const { mouseConfig } = props;
const { isGroup, tableColumn, overflowX, scrollbarWidth, overflowY, scrollbarHeight, scrollXWidth, columnStore, editStore, isColLoading } = reactData;
const { visibleColumn, tableHeight, elemStore, currentRow, customHeight, customMinHeight, customMaxHeight, tHeaderHeight, tFooterHeight } = internalData;
const $xeGanttView = internalData.xeGanttView;
const el = refElem.value;
if (!el || (internalData.tBodyHeight && !el.clientHeight)) {
return;
}
const containerList = ['main', 'left', 'right'];
const { leftList, rightList } = columnStore;
let osbWidth = overflowY ? scrollbarWidth : 0;
let osbHeight = overflowX ? scrollbarHeight : 0;
const emptyPlaceholderElem = refEmptyPlaceholder.value;
const isHeaderRenderOptimize = computeIsHeaderRenderOptimize.value;
const isBodyRenderOptimize = computeIsBodyRenderOptimize.value;
const isFooterRenderOptimize = computeIsFooterRenderOptimize.value;
const scrollbarOpts = computeScrollbarOpts.value;
const mouseOpts = computeMouseOpts.value;
const bodyWrapperElem = getRefElem(elemStore['main-body-wrapper']);
const bodyTableElem = getRefElem(elemStore['main-body-table']);
if (emptyPlaceholderElem) {
emptyPlaceholderElem.style.top = `${tHeaderHeight}px`;
emptyPlaceholderElem.style.height = bodyWrapperElem ? `${bodyWrapperElem.offsetHeight - osbHeight}px` : '';
}
const scrollbarXConf = scrollbarOpts.x || {};
const scrollbarYConf = scrollbarOpts.y || {};
const scrollbarYToLeft = computeScrollbarYToLeft.value;
let xScrollbarVisible = overflowX ? 'visible' : 'hidden';
if (scrollbarXConf.visible === 'visible' || $xeGanttView) {
osbHeight = scrollbarHeight;
xScrollbarVisible = 'visible';
}
else if (scrollbarXConf.visible === 'hidden' || scrollbarXConf.visible === false) {
osbHeight = 0;
xScrollbarVisible = 'hidden';
}
let yScrollbarVisible = overflowY ? 'visible' : 'hidden';
if ((scrollbarYConf.visible === 'hidden' || scrollbarYConf.visible === false) || (($xeGantt && $xeGanttView && $xeGantt.reactData.showRightView) && !scrollbarYToLeft)) {
osbWidth = 0;
yScrollbarVisible = 'hidden';
}
else if (scrollbarYConf.visible === 'visible') {
osbWidth = scrollbarWidth;
yScrollbarVisible = 'visible';
}
let tbHeight = 0;
let bodyMaxHeight = 0;
const bodyMinHeight = customMinHeight - tHeaderHeight - tFooterHeight - osbHeight;
if (customMaxHeight) {
bodyMaxHeight = Math.max(bodyMinHeight, customMaxHeight - tHeaderHeight - tFooterHeight - osbHeight);
}
if (customHeight) {
tbHeight = customHeight - tHeaderHeight - tFooterHeight - osbHeight;
}
if (!tbHeight) {
if (bodyTableElem) {
tbHeight = bodyTableElem.clientHeight;
}
}
if (tbHeight) {
if (bodyMaxHeight) {
tbHeight = Math.min(bodyMaxHeight, tbHeight);
}
tbHeight = Math.max(bodyMinHeight, tbHeight);
}
const xLeftCornerEl = refScrollXLeftCornerElem.value;
const xRightCornerEl = refScrollXRightCornerElem.value;
const scrollXVirtualEl = refScrollXVirtualElem.value;
if (scrollXVirtualEl) {
scrollXVirtualEl.style.height = `${osbHeight}px`;
scrollXVirtualEl.style.visibility = xScrollbarVisible;
}
const xWrapperEl = refScrollXWrapperElem.value;
if (xWrapperEl) {
xWrapperEl.style.width = `${el.clientWidth - osbWidth}px`;
if (scrollbarYToLeft) {
xWrapperEl.style.left = `${osbWidth}px`;
}
else {
xWrapperEl.style.left = '';
}
}
if (xLeftCornerEl) {
if (scrollbarYToLeft) {
xLeftCornerEl.style.width = `${osbWidth}px`;
xLeftCornerEl.style.display = overflowY && osbWidth ? 'block' : '';
}
else {
xLeftCornerEl.style.display = '';
}
}
if (xRightCornerEl) {
if (scrollbarYToLeft) {
xRightCornerEl.style.display = '';
}
else {
xRightCornerEl.style.width = `${osbWidth}px`;
xRightCornerEl.style.display = xScrollbarVisible === 'visible' ? 'block' : '';
}
}
const scrollYVirtualEl = refScrollYVirtualElem.value;
if (scrollYVirtualEl) {
scrollYVirtualEl.style.width = `${osbWidth}px`;
scrollYVirtualEl.style.height = `${tbHeight + tHeaderHeight + tFooterHeight}px`;
scrollYVirtualEl.style.visibility = yScrollbarVisible;
}
const yTopCornerEl = refScrollYTopCornerElem.value;
if (yTopCornerEl) {
yTopCornerEl.style.height = `${tHeaderHeight}px`;
yTopCornerEl.style.display = tHeaderHeight && yScrollbarVisible === 'visible' ? 'block' : '';
}
const yWrapperEl = refScrollYWrapperElem.value;
if (yWrapperEl) {
yWrapperEl.style.height = `${tbHeight}px`;
yWrapperEl.style.top = `${tHeaderHeight}px`;
}
const yBottomCornerEl = refScrollYBottomCornerElem.value;
if (yBottomCornerEl) {
yBottomCornerEl.style.height = `${tFooterHeight}px`;
yBottomCornerEl.style.top = `${tHeaderHeight + tbHeight}px`;
yBottomCornerEl.style.display = tFooterHeight && yScrollbarVisible === 'visible' ? 'block' : '';
}
const rowExpandEl = refRowExpandElem.value;
if (rowExpandEl) {
rowExpandEl.style.height = `${tbHeight}px`;
rowExpandEl.style.top = `${tHeaderHeight}px`;
}
internalData.tBodyHeight = tbHeight;
containerList.forEach((name, index) => {
const fixedType = index > 0 ? name : '';
const layoutList = ['header', 'body', 'footer'];
const isFixedLeft = fixedType === 'left';
let fixedColumn = [];
let fixedWrapperElem;
if (fixedType) {
fixedColumn = isFixedLeft ? leftList : rightList;
fixedWrapperElem = isFixedLeft ? refLeftContainer.value : refRightContainer.value;
}
layoutList.forEach(layout => {
const wrapperElem = getRefElem(elemStore[`${name}-${layout}-wrapper`]);
const currScrollElem = getRefElem(elemStore[`${name}-${layout}-scroll`]);
const tableElem = getRefElem(elemStore[`${name}-${layout}-table`]);
if (layout === 'header') {
// 表头体样式处理
// 横向滚动渲染
let renderColumnList = tableColumn;
const isOptimizeMode = isHeaderRenderOptimize;
if (isGroup) {
renderColumnList = visibleColumn;
}
else {
if (!isOptimizeMode || (!isColLoading && (fixedType || !overflowX))) {
renderColumnList = visibleColumn;
}
if (fixedType) {
// 如果是使用优化模式
if (isOptimizeMode) {
renderColumnList = fixedColumn || [];
}
}
}
const tWidth = renderColumnList.reduce((previous, column) => previous + column.renderWidth, 0);
if (fixedType) {
if (isGroup) {
if (wrapperElem) {
wrapperElem.style.width = scrollXWidth ? `${scrollXWidth}px` : '';
}
}
else {
if (isOptimizeMode) {
if (wrapperElem) {
wrapperElem.style.width = tWidth ? `${tWidth}px` : '';
}
}
else {
if (wrapperElem) {
wrapperElem.style.width = scrollXWidth ? `${scrollXWidth}px` : '';
}
}
}
}
if (currScrollElem) {
currScrollElem.style.height = `${tHeaderHeight}px`;
}
if (tableElem) {
tableElem.style.width = tWidth ? `${tWidth}px` : '';
}
}
else if (layout === 'body') {
if (currScrollElem) {
currScrollElem.style.maxHeight = customMaxHeight ? `${bodyMaxHeight}px` : '';
currScrollElem.style.height = customHeight ? `${tbHeight}px` : '';
currScrollElem.style.minHeight = `${bodyMinHeight}px`;
}
// 如果是固定列
if (fixedWrapperElem) {
if (wrapperElem) {
wrapperElem.style.top = `${tHeaderHeight}px`;
}
fixedWrapperElem.style.height = `${customHeight > 0 ? customHeight : (tableHeight + tHeaderHeight + tFooterHeight + osbHeight)}px`;
fixedWrapperElem.style.width = `${fixedColumn.reduce((previous, column) => previous + column.renderWidth, 0)}px`;
}
let renderColumnList = tableColumn;
const isOptimizeMode = isBodyRenderOptimize;
if (fixedType) {
renderColumnList = visibleColumn;
if (isOptimizeMode) {
renderColumnList = fixedColumn || [];
}
}
const tWidth = renderColumnList.reduce((previous, column) => previous + column.renderWidth, 0);
if (fixedType) {
if (isOptimizeMode) {
if (wrapperElem) {
wrapperElem.style.width = tWidth ? `${tWidth}px` : '';
}
}
else {
if (wrapperElem) {
wrapperElem.style.width = scrollXWidth ? `${scrollXWidth}px` : '';
}
}
}
if (tableElem) {
tableElem.style.width = tWidth ? `${tWidth}px` : '';
// 兼容性处理
tableElem.style.paddingRight = osbWidth && fixedType && (browseObj.firefox || browseObj.safari) ? `${osbWidth}px` : '';
}
const emptyBlockElem = getRefElem(elemStore[`${name}-${layout}-emptyBlock`]);
if (emptyBlockElem) {
emptyBlockElem.style.width = tWidth ? `${tWidth}px` : '';
}
}
else if (layout === 'footer') {
let renderColumnList = tableColumn;
const isOptimizeMode = isFooterRenderOptimize;
if (!isOptimizeMode || (!isColLoading && (fixedType || !overflowX))) {
renderColumnList = visibleColumn;
}
if (fixedType) {
if (isOptimizeMode) {
renderColumnList = fixedColumn || [];
}
}
const tWidth = renderColumnList.reduce((previous, column) => previous + column.renderWidth, 0);
if (fixedType) {
if (isOptimizeMode) {
if (wrapperElem) {
wrapperElem.style.width = tWidth ? `${tWidth}px` : '';
}
}
else {
if (wrapperElem) {
wrapperElem.style.width = scrollXWidth ? `${scrollXWidth}px` : '';
}
}
}
if (currScrollElem) {
currScrollElem.style.height = `${tFooterHeight}px`;
// 如果是固定列
if (fixedWrapperElem) {
if (wrapperElem) {
wrapperElem.style.top = `${customHeight > 0 ? customHeight - tFooterHeight - osbHeight : tableHeight + tHeaderHeight}px`;
}
}
}
if (tableElem) {
tableElem.style.width = tWidth ? `${tWidth}px` : '';
}
}
});
});
if (currentRow) {
$xeTable.setCurrentRow(currentRow);
}
if (mouseConfig && mouseOpts.selected && editStore.selected.row && editStore.selected.column) {
$xeTable.addCellSelectedClass();
}
if ($xeGanttView && $xeGanttView.handleUpdateStyle) {
$xeGanttView.handleUpdateStyle();
}
return nextTick();
};
const checkValidate = (type) => {
if ($xeTable.triggerValidate) {
return $xeTable.triggerValidate(type);
}
return nextTick();
};
/**
* 当单元格发生改变时
* 如果存在规则,则校验
*/
const handleChangeCell = (evnt, params) => {
checkValidate('blur')
.catch((e) => e)
.then(() => {
$xeTable.handleEdit(params, evnt)
.then(() => checkValidate('change'))
.catch((e) => e);
});
};
const handleDefaultSort = () => {
const { sortConfig } = props;
if (sortConfig) {
const sortOpts = computeSortOpts.value;
let { defaultSort } = sortOpts;
if (defaultSort) {
if (!XEUtils.isArray(defaultSort)) {
defaultSort = [defaultSort];
}
if (defaultSort.length) {
(sortConfig.multiple ? defaultSort : defaultSort.slice(0, 1)).forEach((item, index) => {
const { field, order } = item;
if (field && order) {
const column = $xeTable.getColumnByField(field);
if (column && column.sortable) {
column.order = order;
column.sortTime = Date.now() + index;
}
}
});
if (!sortOpts.remote) {
$xeTable.handleTableData(true).then(updateStyle);
}
}
}
}
};
/**
* 处理默认勾选
*/
const handleDefaultSelectionChecked = () => {
const { checkboxConfig } = props;
if (checkboxConfig) {
const { fullDataRowIdData } = internalData;
const checkboxOpts = computeCheckboxOpts.value;
const { checkAll, checkRowKeys } = checkboxOpts;
if (checkAll) {
handleCheckedAllCheckboxRow(true, true);
}
else if (checkRowKeys) {
const defSelection = [];
checkRowKeys.forEach((rowKey) => {
const rowid = encodeRowid(rowKey);
if (fullDataRowIdData[rowid]) {
defSelection.push(fullDataRowIdData[rowid].row);
}
});
handleCheckedCheckboxRow(defSelection, true, true);
}
}
};
/**
* 处理单选框默认勾选
*/
const handleDefaultRadioChecked = () => {
const { radioConfig } = props;
if (radioConfig) {
const { fullDataRowIdData } = internalData;
const radioOpts = computeRadioOpts.value;
const { checkRowKey: rowKey, reserve } = radioOpts;
const rowid = rowKey ? encodeRowid(rowKey) : null;
if (rowid) {
if (fullDataRowIdData[rowid]) {
handleCheckedRadioRow(fullDataRowIdData[rowid].row, true);
}
if (reserve) {
const rowkey = getRowkey($xeTable);
internalData.radioReserveRow = { [rowkey]: rowid };
}
}
}
};
/**
* 处理默认展开行
*/
const handleDefaultRowExpand = () => {
const { expandConfig } = props;
if (expandConfig) {
const { fullDataRowIdData } = internalData;
const expandOpts = computeExpandOpts.value;
const { expandAll, expandRowKeys } = expandOpts;
if (expandAll) {
$xeTable.setAllRowExpand(true);
}
else if (expandRowKeys) {
const defExpandeds = [];
expandRowKeys.forEach((rowKey) => {
const rowid = encodeRowid(rowKey);
if (fullDataRowIdData[rowid]) {
defExpandeds.push(fullDataRowIdData[rowid].row);
}
});
$xeTable.setRowExpand(defExpandeds, true);
}
}
};
const handleRadioReserveRow = (row) => {
const radioOpts = computeRadioOpts.value;
if (radioOpts.reserve) {
internalData.radioReserveRow = row;
}
};
const handleCheckboxReserveRow = (row, checked) => {
const { checkboxReserveRowMap } = internalData;
const checkboxOpts = computeCheckboxOpts.value;
if (checkboxOpts.reserve) {
const rowid = getRowid($xeTable, row);
if (checked) {
checkboxReserveRowMap[rowid] = row;
}
else if (checkboxReserveRowMap[rowid]) {
delete checkboxReserveRowMap[rowid];
}
}
};
const handleCheckedRadioRow = (row, isForce) => {
const radioOpts = computeRadioOpts.value;
const { checkMethod } = radioOpts;
if (row && (isForce || (!checkMethod || checkMethod({ $table: $xeTable, row })))) {
reactData.selectRadioRow = row;
handleRadioReserveRow(row);
}
return nextTick();
};
const handleCheckedCheckboxRow = (rows, value, isForce) => {
if (rows && !XEUtils.isArray(rows)) {
rows = [rows];
}
$xeTable.handleBatchSelectRows(rows, !!value, isForce);
$xeTable.checkSelectionStatus();
return nextTick();
};
const handleCheckedAllCheckboxRow = (checked, isForce) => {
const { treeConfig } = props;
const { isRowGroupStatus } = reactData;
const { afterFullData, afterTreeFullData, afterGroupFullData, checkboxReserveRowMap, selectCheckboxMaps } = internalData;
const treeOpts = computeTreeOpts.value;
const aggregateOpts = computeAggregateOpts.value;
const childrenField = treeOpts.children || treeOpts.childrenField;
const checkboxOpts = computeCheckboxOpts.value;
const { checkField, reserve, checkMethod } = checkboxOpts;
const { handleGetRowId } = createHandleGetRowId($xeTable);
// indeterminateField 仅支持读取
const indeterminateField = checkboxOpts.indeterminateField || checkboxOpts.halfField;
const selectRowMaps = {};
/**
* 绑定属性方式(有污染)
* 必须在行数据存在对应的属性,否则将不响应
*/
if (checkField) {
const checkValFn = (row) => {
if (isForce || (!checkMethod || checkMethod({ $table: $xeTable, row }))) {
if (checked) {
selectRowMaps[handleGetRowId(row)] = row;
}
XEUtils.set(row, checkField, checked);
}
if ((treeConfig || isRowGroupStatus) && indeterminateField) {
XEUtils.set(row, indeterminateField, false);
}
};
// 如果存在选中方法
// 如果方法成立,则更新值,否则忽略该数据
if ((treeConfig || isRowGroupStatus)) {
XEUtils.eachTree(afterFullData, checkValFn, { children: childrenField });
}
else {
afterFullData.forEach(checkValFn);
}
}
else {
/**
* 默认方式(无污染)
* 无需任何属性,直接绑定
*/
if (isRowGroupStatus) {
if (checked) {
/**
* 如果是行分组勾选
* 如果方法成立,则添加到临时集合中
*/
XEUtils.eachTree(afterGroupFullData, (row) => {
if (isForce || (!checkMethod || checkMethod({ $table: $xeTable, row }))) {
const rowid = handleGetRowId(row);
selectRowMaps[rowid] = row;
}
}, { children: aggregateOpts.mapChildrenField });
}
else {
/**
* 如果是树取消
* 如果方法成立,则不添加到临时集合中
*/
if (!isForce && checkMethod) {
XEUtils.eachTree(afterGroupFullData, (row) => {
const rowid = handleGetRowId(row);
if (checkMethod({ $table: $xeTable, row }) ? false : selectCheckboxMaps[rowid]) {
selectRowMaps[rowid] = row;
}
}, { children: aggregateOpts.mapChildrenField });
}
}
}
else if (treeConfig) {
if (checked) {
/**
* 如果是树勾选
* 如果方法成立,则添加到临时集合中
*/
XEUtils.eachTree(afterTreeFullData, (row) => {
if (isForce || (!checkMethod || checkMethod({ $table: $xeTable, row }))) {
const rowid = handleGetRowId(row);
selectRowMaps[rowid] = row;
}
}, { children: childrenField });
}
else {
/**
* 如果是树取消
* 如果方法成立,则不添加到临时集合中
*/
if (!isForce && checkMethod) {
XEUtils.eachTree(afterTreeFullData, (row) => {
const rowid = handleGetRowId(row);
if (checkMethod({ $table: $xeTable, row }) ? false : selectCheckboxMaps[rowid]) {
selectRowMaps[rowid] = row;
}
}, { children: childrenField });
}
}
}
else {
if (checked) {
/**
* 如果是行勾选
* 如果存在选中方法且成立或者本身已勾选,则添加到临时集合中
* 如果不存在选中方法,则添加所有数据到临时集合中
*/
if (!isForce && checkMethod) {
afterFullData.forEach((row) => {
const rowid = handleGetRowId(row);
if (selectCheckboxMaps[rowid] || checkMethod({ $table: $xeTable, row })) {
selectRowMaps[rowid] = row;
}
});
}
else {
afterFullData.forEach(row => {
const rowid = handleGetRowId(row);
selectRowMaps[rowid] = row;
});
}
}
else {
/**
* 如果是行取消
* 如果方法成立,则不添加到临时集合中;如果方法不成立则判断当前是否已勾选,如果已被勾选则添加到新集合中
* 如果不存在选中方法,无需处理,临时集合默认为空
*/
if (!isForce && checkMethod) {
afterFullData.forEach((row) => {
const rowid = handleGetRowId(row);
if (checkMethod({ $table: $xeTable, row }) ? false : selectCheckboxMaps[rowid]) {
selectRowMaps[rowid] = row;
}
});
}
}
}
}
if (reserve) {
if (checked) {
XEUtils.each(selectRowMaps, (row, rowid) => {
checkboxReserveRowMap[rowid] = row;
});
}
else {
afterFullData.forEach((row) => handleCheckboxReserveRow(row, false));
}
}
reactData.updateCheckboxFlag++;
internalData.selectCheckboxMaps = checkField ? {} : selectRowMaps;
reactData.isAllSelected = checked;
reactData.isIndeterminate = false;
internalData.treeIndeterminateRowMaps = {};
$xeTable.checkSelectionStatus();
return nextTick();
};
// 还原展开、选中等相关状态
const handleReserveStatus = () => {
const { treeConfig } = props;
const { expandColumn, selectRadioRow } = reactData;
const { fullDataRowIdData, fullAllDataRowIdData, radioReserveRow, selectCheckboxMaps, treeExpandedMaps, rowExpandedMaps, currentRow } = internalData;
const expandOpts = computeExpandOpts.value;
const treeOpts = computeTreeOpts.value;
const radioOpts = computeRadioOpts.value;
const checkboxOpts = computeCheckboxOpts.value;
// 单选框
if (selectRadioRow && !fullAllDataRowIdData[getRowid($xeTable, selectRadioRow)]) {
reactData.selectRadioRow = null; // 刷新单选行状态
}
// 还原保留选中状态
if (radioOpts.reserve && radioReserveRow) {
const rowid = getRowid($xeTable, radioReserveRow);
if (fullDataRowIdData[rowid]) {
handleCheckedRadioRow(fullDataRowIdData[rowid].row, true);
}
}
// 复选框
internalData.selectCheckboxMaps = getRecoverRowMaps(selectCheckboxMaps); // 刷新多选行状态
reactData.updateCheckboxFlag++;
// 还原保留选中状态
if (checkboxOpts.reserve) {
handleCheckedCheckboxRow(handleReserveRow(internalData.checkboxReserveRowMap), true, true);
}
if (currentRow && !fullAllDataRowIdData[getRowid($xeTable, currentRow)]) {
internalData.currentRow = null; // 刷新当前行状态
}
// 行展开
internalData.rowExpandedMaps = expandColumn ? getRecoverRowMaps(rowExpandedMaps) : {}; // 刷新行展开状态
reactData.rowExpandedFlag++;
// 还原保留状态
if (expandColumn && expandOpts.reserve) {
$xeTable.setRowExpand(handleReserveRow(internalData.rowExpandedReserveRowMap), true);
}
// 树展开
internalData.treeExpandedMaps = treeConfig ? getRecoverRowMaps(treeExpandedMaps) : {}; // 刷新树展开状态
reactData.treeExpandedFlag++;
if (treeConfig && treeOpts.reserve) {
$xeTable.setTreeExpand(handleReserveRow(internalData.treeExpandedReserveRowMap), true);
}
};
/**
* 处理默认展开树节点
*/
const handleDefaultTreeExpand = () => {
const { treeConfig } = props;
if (treeConfig) {
const { fullAllDataRowIdData } = internalData;
const treeOpts = computeTreeOpts.value;
const { expandAll, expandRowKeys } = treeOpts;
if (expandAll) {
$xeTable.setAllTreeExpand(true);
}
else if (expandRowKeys) {
const defExpandeds = [];
expandRowKeys.forEach((rowKey) => {
const rowid = encodeRowid(rowKey);
const rowRest = fullAllDataRowIdData[rowid];
if (rowRest) {
defExpandeds.push(rowRest.row);
}
});
$xeTable.setTreeExpand(defExpandeds, true);
}
}
};
const handleAsyncTreeExpandChilds = (row) => {
const treeOpts = computeTreeOpts.value;
const checkboxOpts = computeCheckboxOpts.value;
const { transform, loadMethod } = treeOpts;
const { checkStrictly } = checkboxOpts;
return new Promise(resolve => {
if (loadMethod) {
const { fullAllDataRowIdData, treeExpandLazyLoadedMaps } = internalData;
const rowid = getRowid($xeTable, row);
const rowRest = fullAllDataRowIdData[rowid];
treeExpandLazyLoadedMaps[rowid] = row;
Promise.resolve(loadMethod({ $table: $xeTable, row })).then((childRecords) => {
if (rowRest) {
rowRest.treeLoaded = true;
}
if (treeExpandLazyLoadedMaps[rowid]) {
delete treeExpandLazyLoadedMaps[rowid];
}
if (!XEUtils.isArray(childRecords)) {
childRecords = [];
}
if (childRecords) {
return $xeTable.loadTreeChildren(row, childRecords).then(childRows => {
const { treeExpandedMaps } = internalData;
if (childRows.length && !treeExpandedMaps[rowid]) {
treeExpandedMaps[rowid] = row;
}
reactData.treeExpandedFlag++;
// 如果当前节点已选中,则展开后子节点也被选中
if (!checkStrictly && $xeTable.isCheckedByCheckboxRow(row)) {
handleCheckedCheckboxRow(childRows, true);
}
return nextTick().then(() => {
if (transform) {
$xeTable.handleTableData();
updateAfterDataIndex();
return nextTick();
}
});
});
}
}).catch(() => {
const { treeExpandLazyLoadedMaps } = internalData;
if (rowRest) {
rowRest.treeLoaded = false;
}
if (treeExpandLazyLoadedMaps[rowid]) {
delete treeExpandLazyLoadedMaps[rowid];
}
}).finally(() => {
reactData.treeExpandedFlag++;
nextTick().then(() => $xeTable.recalculate()).then(() => resolve());
});
}
else {
resolve();
}
});
};
const handleTreeExpandReserve = (row, expanded) => {
const { treeExpandedReserveRowMap } = internalData;
const treeOpts = computeTreeOpts.value;
if (treeOpts.reserve) {
const rowid = getRowid($xeTable, row);
if (expanded) {
treeExpandedReserveRowMap[rowid] = row;
}
else if (treeExpandedReserveRowMap[rowid]) {
delete treeExpandedReserveRowMap[rowid];
}
}
};
const handleAsyncRowExpand = (row) => {
return new Promise(resolve => {
const expandOpts = computeExpandOpts.value;
const { loadMethod } = expandOpts;
if (loadMethod) {
const { fullAllDataRowIdData, rowExpandLazyLoadedMaps } = internalData;
const rowid = getRowid($xeTable, row);
const rowRest = fullAllDataRowIdData[rowid];
rowExpandLazyLoadedMaps[rowid] = row;
loadMethod({ $table: $xeTable, row, rowIndex: $xeTable.getRowIndex(row), $rowIndex: $xeTable.getVMRowIndex(row) }).then(() => {
const { rowExpandedMaps } = internalData;
if (rowRest) {
rowRest.expandLoaded = true;
}
rowExpandedMaps[rowid] = row;
reactData.rowExpandedFlag++;
}).catch(() => {
if (rowRest) {
rowRest.expandLoaded = false;
}
}).finally(() => {
const { rowExpandLazyLoadedMaps } = internalData;
if (rowExpandLazyLoadedMaps[rowid]) {
delete rowExpandLazyLoadedMaps[rowid];
}
reactData.rowExpandedFlag++;
nextTick()
.then(() => $xeTable.recalculate())
.then(() => $xeTable.updateCellAreas())
.then(() => resolve());
});
}
else {
resolve();
}
});
};
const handleRowExpandReserve = (row, expanded) => {
const { rowExpandedReserveRowMap } = internalData;
const expandOpts = computeExpandOpts.value;
if (expandOpts.reserve) {
const rowid = getRowid($xeTable, row);
if (expanded) {
rowExpandedReserveRowMap[rowid] = row;
}
else if (rowExpandedReserveRowMap[rowid]) {
delete rowExpandedReserveRowMap[rowid];
}
}
};
const handleDefaultMergeCells = () => {
const { mergeCells } = props;
if (mergeCells) {
$xeTable.setMergeCells(mergeCells);
}
};
const handleDefaultMergeHeaderItems = () => {
const { mergeHeaderCells } = props;
if (mergeHeaderCells) {
$xeTable.setMergeHeaderCells(mergeHeaderCells);
}
};
const handleDefaultMergeFooterItems = () => {
const { mergeFooterCells, mergeFooterItems } = props;
const mFooterCells = mergeFooterCells || mergeFooterItems;
if (mFooterCells) {
$xeTable.setMergeFooterCells(mFooterCells);
}
};
// 计算可视渲染相关数据
const computeScrollLoad = () => {
return nextTick().then(() => {
const { scrollXLoad, scrollYLoad } = reactData;
const { scrollXStore, scrollYStore } = internalData;
const virtualYOpts = computeVirtualYOpts.value;
const virtualXOpts = computeVirtualXOpts.value;
// 计算 X 逻辑
if (scrollXLoad) {
const { toVisibleIndex: toXVisibleIndex, visibleSize: visibleXSize } = handleVirtualXVisible();
const offsetXSize = Math.max(0, virtualXOpts.oSize ? XEUtils.toNumber(virtualXOpts.oSize) : 0);
scrollXStore.preloadSize = XEUtils.toNumber(virtualXOpts.preSize);
scrollXStore.offsetSize = offsetXSize;
scrollXStore.visibleSize = visibleXSize;
scrollXStore.endIndex = Math.max(scrollXStore.startIndex + scrollXStore.visibleSize + offsetXSize, scrollXStore.endIndex);
scrollXStore.visibleStartIndex = Math.max(scrollXStore.startIndex, toXVisibleIndex);
scrollXStore.visibleEndIndex = Math.min(scrollXStore.endIndex, toXVisibleIndex + visibleXSize);
$xeTable.updateScrollXData().then(() => {
loadScrollXData();
});
}
else {
$xeTable.updateScrollXSpace();
}
// 计算 Y 逻辑
const rowHeight = computeRowHeight();
scrollYStore.rowHeight = rowHeight; // 已废弃
reactData.rowHeight = rowHeight;
const { toVisibleIndex: toYVisibleIndex, visibleSize: visibleYSize } = handleVirtualYVisible();
if (scrollYLoad) {
const offsetYSize = Math.max(0, virtualYOpts.oSize ? XEUtils.toNumber(virtualYOpts.oSize) : 0);
scrollYStore.preloadSize = XEUtils.toNumber(virtualYOpts.preSize);
scrollYStore.offsetSize = offsetYSize;
scrollYStore.visibleSize = visibleYSize;
scrollYStore.endIndex = Math.max(scrollYStore.startIndex + visibleYSize + offsetYSize, scrollYStore.endIndex);
scrollYStore.visibleStartIndex = Math.max(scrollYStore.startIndex, toYVisibleIndex);
scrollYStore.visibleEndIndex = Math.min(scrollYStore.endIndex, toYVisibleIndex + visibleYSize);
$xeTable.updateScrollYData().then(() => {
loadScrollYData();
});
}
else {
$xeTable.updateScrollYSpace();
}
});
};
const calcScrollbar = () => {
const { scrollXWidth, scrollYHeight } = reactData;
const { elemStore } = internalData;
const scrollbarOpts = computeScrollbarOpts.value;
const el = refElem.value;
if (!el || !el.clientWidth) {
return;
}
const bodyWrapperElem = getRefElem(elemStore['main-body-wrapper']);
const headerTableElem = getRefElem(elemStore['main-header-table']);
const footerTableElem = getRefElem(elemStore['main-footer-table']);
const xHandleEl = refScrollXHandleElem.value;
const yHandleEl = refScrollYHandleElem.value;
let overflowY = false;
let overflowX = false;
if (bodyWrapperElem) {
overflowY = scrollYHeight > bodyWrapperElem.clientHeight;
if (yHandleEl) {
reactData.scrollbarWidth = scrollbarOpts.width || (yHandleEl.offsetWidth - yHandleEl.clientWidth) || 14;
}
reactData.overflowY = overflowY;
overflowX = scrollXWidth > bodyWrapperElem.clientWidth;
if (xHandleEl) {
reactData.scrollbarHeight = scrollbarOpts.height || (xHandleEl.offsetHeight - xHandleEl.clientHeight) || 14;
}
const hHeight = headerTableElem ? headerTableElem.clientHeight : 0;
const fHeight = footerTableElem ? footerTableElem.clientHeight : 0;
internalData.tableHeight = bodyWrapperElem.offsetHeight;
internalData.tHeaderHeight = hHeight;
internalData.tFooterHeight = fHeight;
reactData.overflowX = overflowX;
reactData.parentHeight = Math.max(hHeight + fHeight + 20, $xeTable.getParentHeight());
}
if (overflowX) {
$xeTable.checkScrolling();
}
};
const handleRecalculateStyle = (reFull, reWidth, reHeight) => {
const el = refElem.value;
if (!el || !el.clientWidth) {
return nextTick();
}
const varEl = refVarElem.value;
if (varEl) {
const [defEl, mediumEl, smallEl, miniEl] = varEl.children;
calcVarRowHeightConfig('default', defEl);
calcVarRowHeightConfig('medium', mediumEl);
calcVarRowHeightConfig('small', smallEl);
calcVarRowHeightConfig('mini', miniEl);
}
if (reWidth) {
calcCellWidth();
}
if (reWidth || reFull) {
autoCellWidth();
}
calcScrollbar();
updateStyle();
updateRowExpandStyle();
if (reFull) {
updateTreeLineStyle();
}
internalData.rceRunTime = Date.now();
return computeScrollLoad().then(() => {
// 初始化时需要在列计算之后再执行优化运算,达到最优显示效果
if (reWidth) {
calcCellWidth();
}
if (reWidth || reFull) {
autoCellWidth();
}
if (reHeight) {
calcCellHeight();
}
updateStyle();
calcScrollbar();
if (reFull) {
updateRowOffsetTop();
}
updateRowExpandStyle();
if (reFull) {
updateTreeLineStyle();
}
internalData.rceRunTime = Date.now();
if (reFull) {
return computeScrollLoad();
}
});
};
const defaultMinRunDelay = 50;
const handleLazyRecalculate = (reFull, reWidth, reHeight, options) => {
const minRunDelay = (options ? options.minRunDelay : defaultMinRunDelay) || defaultMinRunDelay;
return new Promise(resolve => {
const $xeGanttView = internalData.xeGanttView;
const { customStore, tableData, tableColumn } = reactData;
const { rceTimeout, rceRunTime } = internalData;
const resizeOpts = computeResizeOpts.value;
let rceDelay = internalData.rceDelay;
// 如果在500毫秒内频繁执行,则执行次数减缓
if (rceRunTime && rceRunTime > Date.now() - 500) {
rceDelay = Math.min(Math.max(60, Math.min(800, tableData.length / 8)), rceDelay + 50);
}
else {
rceDelay = 0;
}
internalData.rceDelay = rceDelay;
const refreshDelay = resizeOpts.refreshDelay || 30;
const reDelay = rceDelay + refreshDelay;
const el = refElem.value;
if (el && el.clientWidth) {
autoCellWidth();
updateRowExpandStyle();
}
if (customStore.visible && $xeTable.handleCustomStyle) {
$xeTable.handleCustomStyle();
}
const renderCellSize = tableData.length * tableColumn.length;
// 渲染量低的场景
if (renderCellSize < 400) {
rceDelay = 20;
}
else if (renderCellSize < 600) {
rceDelay = 40;
}
else if (renderCellSize < 800) {
rceDelay = 80;
}
if (rceTimeout) {
clearTimeout(rceTimeout);
// 多少毫秒内至少执行一次
if (rceRunTime && rceRunTime + minRunDelay < Date.now()) {
resolve(handleRecalculateStyle(reFull, reWidth, reHeight));
}
else {
nextTick(() => {
resolve();
});
}
}
else {
resolve(handleRecalculateStyle(reFull, reWidth, reHeight));
}
if ($xeGanttView && $xeGanttView.handleLazyRecalculate) {
$xeGanttView.handleLazyRecalculate();
}
internalData.rceTimeout = setTimeout(() => {
internalData.rceDelay = 0;
internalData.rceTimeout = undefined;
handleRecalculateStyle(reFull, reWidth, reHeight);
if ($xeGanttView && $xeGanttView.handleLazyRecalculate) {
$xeGanttView.handleLazyRecalculate();
}
}, reDelay);
});
};
const handleResizeEvent = () => {
if (internalData.rsePending) {
return;
}
internalData.rsePending = true;
handleLazyRecalculate(true, true, true, {
minRunDelay: 200
}).then(() => {
internalData.rsePending = false;
}).catch(() => {
internalData.rsePending = false;
});
};
const handleUpdateAggValues = () => {
const { visibleColumn } = internalData;
const aggCols = [];
visibleColumn.forEach(column => {
if (column.aggFunc) {
aggCols.push(column);
}
});
reactData.aggHandleAggColumns = aggCols;
};
const handleUpdateRowGroup = (groupFields) => {
const aggGroupFields = [];
const aggGroupConfs = [];
if (groupFields) {
(XEUtils.isArray(groupFields) ? groupFields : [groupFields]).forEach(field => {
aggGroupFields.push(field);
aggGroupConfs.push({
field
});
});
}
reactData.rowGroupList = aggGroupConfs;
reactData.aggHandleFields = aggGroupFields;
handleUpdateAggValues();
};
const handleeGroupSummary = (aggList) => {
const { fullColumnFieldData } = internalData;
const aggregateOpts = computeAggregateOpts.value;
const aggFuncColumns = computeAggFuncColumns.value;
const { mapChildrenField } = aggregateOpts;
const aggCalcMethod = aggregateOpts.calcValuesMethod || aggregateOpts.countMethod || aggregateOpts.aggregateMethod;
if (mapChildrenField) {
XEUtils.lastEach(aggList, aggRow => {
let count = 0;
XEUtils.each(aggRow[mapChildrenField], (row) => {
if (row.isAggregate) {
count += row.childCount || 0;
}
else {
count++;
}
});
aggRow.childCount = count;
});
if ($xeTable.handlePivotTableAggData) {
$xeTable.handlePivotTableAggData(aggList);
}
else {
if (aggFuncColumns.length) {
XEUtils.lastEach(aggList, aggRow => {
const aggDtObj = {};
const aggData = aggRow.aggData;
const groupField = aggRow.groupField;
const groupContent = aggRow.groupContent;
const childList = mapChildrenField ? (aggRow[mapChildrenField] || []) : [];
const childCount = aggRow.childCount;
const colRest = fullColumnFieldData[groupField] || {};
aggFuncColumns.forEach(column => {
const { field } = column;
const currAggData = aggData ? aggData[field] : null;
const ctParams = {
$table: $xeTable,
groupField,
groupColumn: (colRest ? colRest.column : null),
column,
groupValue: groupContent,
childList,
childCount,
aggValue: currAggData ? currAggData.value : 0,
/**
* 已废弃
* @deprecated
*/
children: childList,
/**
* 已废弃
* @deprecated
*/
totalValue: childCount
};
let aggVal = 0;
// 如果下层同时也是分组
if (childList.length && childList[0].isAggregate) {
XEUtils.each(childList, (row) => {
if (row.isAggregate) {
const currAggData = row.aggData[field];
if (currAggData) {
aggVal += currAggData.value;
}
}
});
}
else {
aggVal = aggCalcMethod ? aggCalcMethod(ctParams) : aggRow.childCount;
}
aggDtObj[field] = {
type: 'count',
value: aggVal,
label: aggVal
};
});
aggRow.aggData = aggDtObj;
});
}
}
}
};
const updateGroupData = () => {
const { aggregateConfig, rowGroupConfig } = props;
const { isRowGroupStatus } = reactData;
const { tableFullGroupData } = internalData;
const aggregateOpts = computeAggregateOpts.value;
const { mapChildrenField } = aggregateOpts;
if ((aggregateConfig || rowGroupConfig) && isRowGroupStatus) {
const aggList = [];
XEUtils.eachTree(tableFullGroupData, row => {
if (row.isAggregate) {
aggList.push(row);
}
}, { children: mapChildrenField });
handleeGroupSummary(aggList);
}
};
const handleGroupData = (list, rowGroups, isCombinedField) => {
let fullData = list;
let treeData = list;
if (rowGroups) {
const aggregateOpts = computeAggregateOpts.value;
const { rowField, parentField, separator, childrenField, mapChildrenField } = aggregateOpts;
const rowOpts = computeRowOpts.value;
const checkboxOpts = computeCheckboxOpts.value;
const { checkField } = checkboxOpts;
const indeterminateField = checkboxOpts.indeterminateField || checkboxOpts.halfField;
const rgItem = rowGroups[0];
if (rgItem && rowField && parentField && childrenField && mapChildrenField) {
fullData = [];
treeData = [];
const groupField = rgItem.field;
const groupColumn = $xeTable.getColumnByField(groupField);
const groupMaps = {};
const groupCombinedMaps = {};
const aggList = [];
const rowkey = getRowkey($xeTable);
list.forEach((row) => {
const cellValue = groupColumn ? $xeTable.getCellLabel(row, groupColumn) : XEUtils.get(row, groupField);
let groupValue = XEUtils.eqNull(cellValue) ? '' : cellValue;
if (isCombinedField) {
const groupVals = [groupValue];
rowGroups.slice(1).forEach(ogItem => {
const ogField = ogItem.field;
const ogColumn = $xeTable.getColumnByField(ogField);
const ocValue = ogColumn ? $xeTable.getCellLabel(row, ogColumn) : XEUtils.get(row, ogField);
const ogValue = XEUtils.eqNull(ocValue) ? '' : ocValue;
groupValue += (separator || ' / ') + ogValue;
groupVals.push(ogValue);
});
if (!groupCombinedMaps[groupValue]) {
groupCombinedMaps[groupValue] = groupVals;
}
}
let childList = groupMaps[groupValue];
if (!childList) {
childList = [];
groupMaps[groupValue] = childList;
}
if (row.isAggregate) {
row.isAggregate = undefined;
}
childList.push(row);
});
if (isCombinedField) {
XEUtils.objectEach(groupMaps, (childList, groupValue) => {
const aggRow = {
isAggregate: true,
aggData: {},
groupContent: groupValue,
groupCombineds: groupCombinedMaps[groupValue],
groupField,
childCount: 0,
[rowField]: getRowUniqueId(),
[parentField]: null,
[childrenField]: childList,
[mapChildrenField]: childList
};
aggRow[rowkey] = createRowId(rowOpts, aggRow, rowkey);
if (checkField) {
aggRow[checkField] = false;
}
if (indeterminateField) {
aggRow[indeterminateField] = false;
}
aggList.push(aggRow);
treeData.push(aggRow);
fullData.push(aggRow);
});
}
else {
XEUtils.objectEach(groupMaps, (childList, groupValue) => {
const { fullData: childFullData, treeData: childTreeData } = handleGroupData(childList, rowGroups.slice(1));
const aggRow = {
isAggregate: true,
aggData: {},
groupContent: groupValue,
groupCombineds: [],
groupField,
childCount: 0,
[rowField]: getRowUniqueId(),
[parentField]: null,
[childrenField]: childTreeData,
[mapChildrenField]: childTreeData
};
aggRow[rowkey] = createRowId(rowOpts, aggRow, rowkey);
if (checkField) {
aggRow[checkField] = false;
}
if (indeterminateField) {
aggRow[indeterminateField] = false;
}
aggList.push(aggRow);
treeData.push(aggRow);
fullData.push(aggRow);
if (childFullData.length) {
fullData.push(...childFullData);
}
});
}
handleeGroupSummary(aggList);
}
}
return {
treeData,
fullData
};
};
const initGroupData = (list, rowGroups) => {
const aggregateOpts = computeAggregateOpts.value;
const { mode } = aggregateOpts;
const isCombinedField = mode === 'combined';
const groupRest = handleGroupData(list, rowGroups, isCombinedField);
return groupRest;
};
const initData = () => {
const { data } = props;
loadTableData(data || [], true, true).then(() => {
if (data && data.length) {
internalData.inited = true;
internalData.initStatus = true;
handleLoadDefaults();
}
handleInitDefaults();
updateStyle();
if (!reactData.isAllOverflow) {
calcCellHeight();
updateRowOffsetTop();
}
});
nextTick(() => {
dispatchEvent('ready', {}, null);
});
};
/**
* 加载表格数据
* @param {Array} datas 数据
*/
const loadTableData = (datas, isReload, isReset) => {
const { keepSource, treeConfig, rowGroupConfig, aggregateConfig } = props;
const { rowGroupList, scrollYLoad: oldScrollYLoad } = reactData;
const { initStatus, scrollYStore, scrollXStore, lastScrollLeft, lastScrollTop } = internalData;
const rowOpts = computeRowOpts.value;
const treeOpts = computeTreeOpts.value;
const expandOpts = computeExpandOpts.value;
const { transform } = treeOpts;
const childrenField = treeOpts.children || treeOpts.childrenField;
let treeData = [];
let fullData = reactive(datas ? datas.slice(0) : []); // 转为响应式数据
if (fullData.length > supportMaxRow) {
errLog('vxe.error.errMaxRow', [supportMaxRow]);
}
if (treeConfig && rowGroupList.length) {
errLog('vxe.error.noTree', ['aggregate-config']);
return nextTick();
}
if (rowOpts.drag && rowGroupList.length) {
errLog('vxe.error.errConflicts', ['row-config.drag', 'aggregate-config']);
return nextTick();
}
let isRGroup = false;
if (treeConfig) {
if (transform) {
// 树结构自动转换
if (!treeOpts.rowField) {
errLog('vxe.error.reqProp', ['tree-config.rowField']);
}
if (!treeOpts.parentField) {
errLog('vxe.error.reqProp', ['tree-config.parentField']);
}
if (!childrenField) {
errLog('vxe.error.reqProp', ['tree-config.childrenField']);
}
if (!treeOpts.mapChildrenField) {
errLog('vxe.error.reqProp', ['tree-config.mapChildrenField']);
}
if (childrenField === treeOpts.mapChildrenField) {
errLog('vxe.error.errConflicts', ['tree-config.childrenField', 'tree-config.mapChildrenField']);
}
// fullData.forEach(row => {
// if (row[treeOpts.children] && row[treeOpts.children].length) {
// warnLog('vxe.error.errConflicts', ['tree-config.transform', `row.${treeOpts.children}`])
// }
// })
treeData = XEUtils.toArrayTree(fullData, {
key: treeOpts.rowField,
parentKey: treeOpts.parentField,
children: childrenField,
mapChildren: treeOpts.mapChildrenField
});
fullData = treeData.slice(0);
}
else {
treeData = fullData.slice(0);
}
}
else if ((aggregateConfig || rowGroupConfig) && rowGroupList.length) {
const groupRest = initGroupData(fullData, rowGroupList);
treeData = groupRest.treeData;
fullData = groupRest.fullData;
isRGroup = true;
}
reactData.isRowGroupStatus = isRGroup;
scrollYStore.startIndex = 0;
scrollYStore.endIndex = 1;
scrollXStore.startIndex = 0;
scrollXStore.endIndex = 1;
internalData.cvCacheMaps = {};
reactData.isRowLoading = true;
reactData.scrollVMLoading = false;
reactData.treeExpandedFlag++;
reactData.rowExpandedFlag++;
internalData.insertRowMaps = {};
reactData.insertRowFlag++;
internalData.removeRowMaps = {};
reactData.removeRowFlag++;
internalData.fullCellHeightMaps = {};
internalData.fullCellStoreMaps = {};
const sYLoad = updateScrollYStatus(fullData);
// 全量数据
internalData.tableFullData = fullData;
internalData.tableFullTreeData = isRGroup ? [] : treeData;
internalData.tableFullGroupData = isRGroup ? treeData : [];
// 缓存数据
$xeTable.cacheRowMap(isReset);
// 原始数据
internalData.tableSynchData = datas;
if (isReset) {
internalData.isResizeCellHeight = false;
}
// 克隆原数据,用于显示编辑状态,与编辑值做对比
if (keepSource) {
$xeTable.cacheSourceMap(fullData);
}
if ($xeTable.clearCellAreas && props.mouseConfig) {
$xeTable.clearCellAreas();
$xeTable.clearCopyCellArea();
}
$xeTable.clearMergeCells();
$xeTable.clearMergeFooterItems();
$xeTable.clearHistory();
$xeTable.handleTableData(true);
$xeTable.updateFooter();
$xeTable.handleUpdateBodyMerge();
return nextTick().then(() => {
updateHeight();
updateStyle();
}).then(() => {
computeScrollLoad();
syncGanttScrollYStatus();
}).then(() => {
const virtualYOpts = computeVirtualYOpts.value;
// 是否启用了虚拟滚动
if (sYLoad) {
scrollYStore.endIndex = scrollYStore.visibleSize;
}
if (sYLoad) {
if (reactData.expandColumn && expandOpts.mode !== 'fixed') {
errLog('vxe.error.notConflictProp', ['column.type="expand', 'expand-config.mode="fixed"']);
}
if (virtualYOpts.mode === 'scroll' && reactData.expandColumn && expandOpts.mode === 'fixed') {
warnLog('vxe.error.notConflictProp', ['virtual-y-config.mode=scroll', 'expand-config.mode=inside']);
}
// if (showOverflow) {
// if (!rowOpts.height) {
// const errColumn = internalData.tableFullColumn.find(column => column.showOverflow === false)
// if (errColumn) {
// errLog('vxe.error.errProp', [`column[field="${errColumn.field}"].show-overflow=false`, 'show-overflow=true'])
// }
// }
// }
if (!(props.height || props.maxHeight)) {
errLog('vxe.error.reqSupportProp', ['virtual-y-config.enabled = true', 'height | max-height']);
}
// if (!props.showOverflow) {
// warnLog('vxe.error.reqProp', ['table.show-overflow'])
// }
// if (props.spanMethod) {
// warnLog('vxe.error.scrollErrProp', ['span-method'])
// }
}
handleReserveStatus();
$xeTable.checkSelectionStatus();
$xeTable.dispatchEvent('data-change', {
visibleColumn: internalData.visibleColumn,
visibleData: internalData.afterFullData
}, null);
return new Promise(resolve => {
nextTick()
.then(() => handleRecalculateStyle(false, false, false))
.then(() => {
handleRecalculateStyle(false, true, true);
updateRowOffsetTop();
})
.then(() => {
let targetScrollLeft = lastScrollLeft;
let targetScrollTop = lastScrollTop;
const virtualXOpts = computeVirtualXOpts.value;
const virtualYOpts = computeVirtualYOpts.value;
// 是否在更新数据之后自动滚动重置滚动条
if (virtualXOpts.scrollToLeftOnChange) {
targetScrollLeft = 0;
}
if (virtualYOpts.scrollToTopOnChange) {
targetScrollTop = 0;
}
reactData.isRowLoading = false;
handleRecalculateStyle(false, false, false);
updateTreeLineStyle();
syncGanttScrollYStatus();
// 如果是自动行高,特殊情况需调用 recalculate 手动刷新
if (!props.showOverflow) {
setTimeout(() => {
handleLazyRecalculate(false, true, true);
setTimeout(() => handleLazyRecalculate(false, true, true), 3000);
}, 2000);
}
// 是否变更虚拟滚动
if (oldScrollYLoad === sYLoad) {
restoreScrollLocation($xeTable, targetScrollLeft, targetScrollTop)
.then(() => {
handleRecalculateStyle(false, true, true);
updateRowOffsetTop();
updateTreeLineStyle();
nextTick(() => resolve());
});
}
else {
setTimeout(() => {
restoreScrollLocation($xeTable, targetScrollLeft, targetScrollTop)
.then(() => {
handleRecalculateStyle(false, true, true);
updateRowOffsetTop();
updateTreeLineStyle();
nextTick(() => resolve());
});
});
}
});
}).then(() => {
if (initStatus) {
dispatchEvent('data-rendered', {
isReload,
visibleColumn: internalData.visibleColumn,
visibleData: internalData.afterFullData
}, null);
}
else {
dispatchEvent('init-rendered', {
visibleColumn: internalData.visibleColumn,
visibleData: internalData.afterFullData
}, null);
}
});
});
};
/**
* 处理数据加载默认行为
* 默认执行一次,除非被重置
*/
const handleLoadDefaults = () => {
handleDefaultSelectionChecked();
handleDefaultRadioChecked();
handleDefaultRowExpand();
handleDefaultTreeExpand();
handleDefaultRowGroupExpand();
handleDefaultMergeCells();
handleDefaultMergeHeaderItems();
handleDefaultMergeFooterItems();
nextTick(() => {
setTimeout(() => $xeTable.recalculate());
});
};
/**
* 处理初始化的默认行为
* 只会执行一次
*/
const handleInitDefaults = () => {
handleDefaultSort();
};
const handleTableColumn = () => {
const { scrollXLoad } = reactData;
const { visibleColumn, scrollXStore, fullColumnIdData } = internalData;
const tableColumn = scrollXLoad ? visibleColumn.slice(scrollXStore.startIndex, scrollXStore.endIndex) : visibleColumn.slice(0);
tableColumn.forEach((column, $index) => {
const colid = column.id;
const colRest = fullColumnIdData[colid];
if (colRest) {
colRest.$index = $index;
}
});
reactData.tableColumn = tableColumn;
};
const handleUpdateColumn = () => {
const columnList = XEUtils.orderBy(internalData.collectColumn, 'renderSortNumber');
internalData.collectColumn = columnList;
const tFullColumn = getColumnList(columnList);
internalData.tableFullColumn = tFullColumn;
reactData.updateColFlag++;
cacheColumnMap();
};
const loadScrollXData = () => {
const { isScrollXBig } = reactData;
const { mergeBodyList, mergeFooterList, mergeBodyRowMaps, scrollXStore } = internalData;
const { preloadSize, startIndex, endIndex, offsetSize } = scrollXStore;
const { toVisibleIndex, visibleSize } = handleVirtualXVisible();
const offsetItem = {
startIndex: Math.max(0, isScrollXBig ? toVisibleIndex - 1 : toVisibleIndex - 1 - offsetSize - preloadSize),
endIndex: isScrollXBig ? toVisibleIndex + visibleSize : toVisibleIndex + visibleSize + offsetSize + preloadSize
};
scrollXStore.visibleStartIndex = toVisibleIndex - 1;
scrollXStore.visibleEndIndex = toVisibleIndex + visibleSize + 1;
calculateMergerOffsetIndex(mergeBodyList.concat(mergeFooterList), mergeBodyRowMaps, offsetItem, 'col');
const { startIndex: offsetStartIndex, endIndex: offsetEndIndex } = offsetItem;
if (toVisibleIndex <= startIndex || toVisibleIndex >= endIndex - visibleSize - 1) {
if (startIndex !== offsetStartIndex || endIndex !== offsetEndIndex) {
scrollXStore.startIndex = offsetStartIndex;
scrollXStore.endIndex = offsetEndIndex;
$xeTable.updateScrollXData();
}
}
$xeTable.closeTooltip();
};
const parseColumns = (isReset) => {
// const { showOverflow } = props
// const rowOpts = computeRowOpts.value
const leftList = [];
const centerList = [];
const rightList = [];
const { isGroup, columnStore } = reactData;
const { collectColumn, tableFullColumn, scrollXStore, fullColumnIdData } = internalData;
// 如果是分组表头,如果子列全部被隐藏,则根列也隐藏
if (isGroup) {
const leftGroupList = [];
const centerGroupList = [];
const rightGroupList = [];
XEUtils.eachTree(collectColumn, (column, index, items, path, parentColumn) => {
const isColGroup = hasChildrenList(column);
// 如果是分组,必须按组设置固定列,不允许给子列设置固定
if (parentColumn && parentColumn.fixed) {
column.fixed = parentColumn.fixed;
}
if (parentColumn && (column.fixed || '') !== (parentColumn.fixed || '')) {
errLog('vxe.error.groupFixed');
}
if (isColGroup) {
column.visible = !!XEUtils.findTree(column.children, (subColumn) => hasChildrenList(subColumn) ? false : subColumn.visible);
}
else if (column.visible) {
if (column.fixed === 'left') {
leftList.push(column);
}
else if (column.fixed === 'right') {
rightList.push(column);
}
else {
centerList.push(column);
}
}
});
collectColumn.forEach((column) => {
if (column.visible) {
if (column.fixed === 'left') {
leftGroupList.push(column);
}
else if (column.fixed === 'right') {
rightGroupList.push(column);
}
else {
centerGroupList.push(column);
}
}
});
reactData.tableGroupColumn = leftGroupList.concat(centerGroupList).concat(rightGroupList);
}
else {
// 重新分配列
tableFullColumn.forEach((column) => {
if (column.visible) {
if (column.fixed === 'left') {
leftList.push(column);
}
else if (column.fixed === 'right') {
rightList.push(column);
}
else {
centerList.push(column);
}
}
});
}
const visibleColumn = leftList.concat(centerList).concat(rightList);
internalData.visibleColumn = visibleColumn;
updateColumnOffsetLeft();
const sXLoad = updateScrollXStatus();
reactData.hasFixedColumn = leftList.length > 0 || rightList.length > 0;
Object.assign(columnStore, { leftList, centerList, rightList });
if (sXLoad) {
// if (showOverflow) {
// if (!rowOpts.height) {
// const errColumn = internalData.tableFullColumn.find(column => column.showOverflow === false)
// if (errColumn) {
// errLog('vxe.error.errProp', [`column[field="${errColumn.field}"].show-overflow=false`, 'show-overflow=true'])
// }
// }
// }
// if (props.showHeader && !props.showHeaderOverflow) {
// warnLog('vxe.error.reqProp', ['show-header-overflow'])
// }
// if (props.showFooter && !props.showFooterOverflow) {
// warnLog('vxe.error.reqProp', ['show-footer-overflow'])
// }
if (props.spanMethod) {
warnLog('vxe.error.scrollErrProp', ['span-method']);
}
if (props.footerSpanMethod) {
warnLog('vxe.error.scrollErrProp', ['footer-span-method']);
}
if (isReset) {
const { visibleSize } = handleVirtualXVisible();
scrollXStore.startIndex = 0;
scrollXStore.endIndex = visibleSize;
scrollXStore.visibleSize = visibleSize;
scrollXStore.visibleStartIndex = 0;
scrollXStore.visibleEndIndex = visibleSize;
}
}
// 如果列被显示/隐藏,则清除合并状态
// 如果列被设置为固定,则清除合并状态
if (visibleColumn.length !== internalData.visibleColumn.length || !internalData.visibleColumn.every((column, index) => column === visibleColumn[index])) {
$xeTable.clearMergeCells();
$xeTable.clearMergeFooterItems();
}
visibleColumn.forEach((column, index) => {
const colid = column.id;
const colRest = fullColumnIdData[colid];
if (colRest) {
colRest._index = index;
}
});
handleTableColumn();
handleUpdateAggValues();
if (isReset) {
updateColumnOffsetLeft();
return $xeTable.updateFooter().then(() => {
return $xeTable.recalculate();
}).then(() => {
$xeTable.updateCellAreas();
return $xeTable.recalculate();
});
}
return $xeTable.updateFooter();
};
const initColumnHierarchy = () => {
const { collectColumn } = internalData;
const fullColIdData = {};
const fullColFieldData = {};
let sortIndex = 1;
XEUtils.eachTree(collectColumn, (column, index, items, path, parentColumn) => {
const { id: colid, field } = column;
const parentId = parentColumn ? parentColumn.id : null;
const rest = { $index: -1, _index: -1, column, colid, index, items, parent: parentColumn || null, width: 0, oLeft: 0 };
column.parentId = parentId;
column.defaultParentId = parentId;
column.sortNumber = sortIndex;
column.renderSortNumber = sortIndex;
sortIndex++;
if (field) {
if (fullColFieldData[field]) {
errLog('vxe.error.colRepet', ['field', field]);
}
fullColFieldData[field] = rest;
}
fullColIdData[colid] = rest;
});
internalData.fullColumnIdData = fullColIdData;
internalData.fullColumnFieldData = fullColFieldData;
};
const buildColumnInfo = () => {
const { scrollXLoad, scrollYLoad, expandColumn } = reactData;
const expandOpts = computeExpandOpts.value;
cacheColumnMap();
parseColumns(true).then(() => {
if (reactData.scrollXLoad) {
loadScrollXData();
}
});
$xeTable.clearHeaderFormatterCache();
$xeTable.clearMergeCells();
$xeTable.clearMergeFooterItems();
$xeTable.handleTableData(true);
$xeTable.handleAggregateSummaryData();
if ((scrollXLoad || scrollYLoad) && (expandColumn && expandOpts.mode !== 'fixed')) {
warnLog('vxe.error.scrollErrProp', ['column.type=expand']);
}
return nextTick().then(() => {
if ($xeToolbar) {
$xeToolbar.syncUpdate({
collectColumn: internalData.collectColumn,
$table: $xeTable
});
}
if ($xeTable.handleUpdateCustomColumn) {
$xeTable.handleUpdateCustomColumn();
}
const columnOpts = computeColumnOpts.value;
if (props.showCustomHeader && reactData.isGroup && (columnOpts.resizable || props.resizable)) {
warnLog('vxe.error.notConflictProp', ['show-custom-header & colgroup', 'column-config.resizable=false']);
}
reactData.isColLoading = false;
return handleLazyRecalculate(false, true, true);
});
};
const handleInitColumn = (collectColumn) => {
internalData.collectColumn = collectColumn;
const tFullColumn = getColumnList(collectColumn);
internalData.tableFullColumn = tFullColumn;
reactData.updateColFlag++;
reactData.isColLoading = true;
initColumnHierarchy();
return Promise.resolve(restoreCustomStorage()).then(() => {
return buildColumnInfo();
});
};
const updateScrollXStatus = (fullColumn) => {
const virtualXOpts = computeVirtualXOpts.value;
const allCols = fullColumn || internalData.tableFullColumn;
// 如果gt为0,则总是启用
const scrollXLoad = !!virtualXOpts.enabled && virtualXOpts.gt > -1 && (virtualXOpts.gt === 0 || virtualXOpts.gt < allCols.length);
reactData.scrollXLoad = scrollXLoad;
return scrollXLoad;
};
const syncGanttScrollYStatus = () => {
const $xeGanttView = internalData.xeGanttView;
if ($xeGanttView && $xeGanttView.handleUpdateSYStatus) {
$xeGanttView.handleUpdateSYStatus(reactData.scrollYLoad);
}
};
const updateScrollYStatus = (fullData) => {
const { treeConfig } = props;
const virtualYOpts = computeVirtualYOpts.value;
const treeOpts = computeTreeOpts.value;
const { transform } = treeOpts;
const allList = fullData || internalData.tableFullData;
// 如果gt为0,则总是启用
let scrollYLoad = !!virtualYOpts.enabled && virtualYOpts.gt > -1 && (virtualYOpts.gt === 0 || virtualYOpts.gt < allList.length);
if (scrollYLoad && (treeConfig && !transform)) {
errLog('vxe.error.notSupportProp', ['[table] virtual-y-config.enabled=true', 'tree-config.transform=false', 'tree-config.transform=true']);
scrollYLoad = false;
}
reactData.scrollYLoad = scrollYLoad;
syncGanttScrollYStatus();
return scrollYLoad;
};
/**
* 展开与收起树节点
* @param rows
* @param expanded
* @returns
*/
const handleBaseTreeExpand = (rows, expanded) => {
const { treeNodeColumn } = reactData;
const { fullAllDataRowIdData, tableFullTreeData, treeExpandedMaps, treeExpandLazyLoadedMaps } = internalData;
const treeOpts = computeTreeOpts.value;
const { reserve, lazy, accordion, toggleMethod } = treeOpts;
const childrenField = treeOpts.children || treeOpts.childrenField;
const hasChildField = treeOpts.hasChild || treeOpts.hasChildField;
const result = [];
const columnIndex = $xeTable.getColumnIndex(treeNodeColumn);
const $columnIndex = $xeTable.getVMColumnIndex(treeNodeColumn);
const _columnIndex = $xeTable.getVTColumnIndex(treeNodeColumn);
const { handleGetRowId } = createHandleGetRowId($xeTable);
let validRows = toggleMethod ? rows.filter((row) => toggleMethod({ $table: $xeTable, expanded, column: treeNodeColumn, columnIndex, $columnIndex, _columnIndex, row })) : rows;
if (accordion) {
validRows = validRows.length ? [validRows[validRows.length - 1]] : [];
// 同一级只能展开一个
const matchObj = XEUtils.findTree(tableFullTreeData, item => item === validRows[0], { children: childrenField });
if (matchObj) {
matchObj.items.forEach(item => {
const rowid = handleGetRowId(item);
if (treeExpandedMaps[rowid]) {
delete treeExpandedMaps[rowid];
}
});
}
}
if (expanded) {
validRows.forEach((row) => {
const rowid = handleGetRowId(row);
if (!treeExpandedMaps[rowid]) {
const rowRest = fullAllDataRowIdData[rowid];
if (rowRest) {
const isLoad = lazy && row[hasChildField] && !rowRest.treeLoaded && !treeExpandLazyLoadedMaps[rowid];
// 是否使用懒加载
if (isLoad) {
result.push(handleAsyncTreeExpandChilds(row));
}
else {
if (row[childrenField] && row[childrenField].length) {
treeExpandedMaps[rowid] = row;
}
}
}
}
});
}
else {
validRows.forEach(item => {
const rowid = handleGetRowId(item);
if (treeExpandedMaps[rowid]) {
delete treeExpandedMaps[rowid];
}
});
}
if (reserve) {
validRows.forEach((row) => handleTreeExpandReserve(row, expanded));
}
reactData.treeExpandedFlag++;
return Promise.all(result).then(() => {
updateTreeLineStyle();
return $xeTable.recalculate();
});
};
/**
* 虚拟树的展开与收起
* @param rows
* @param expanded
* @returns
*/
const handleVirtualTreeExpand = (rows, expanded) => {
const { lastScrollLeft, lastScrollTop } = internalData;
return handleBaseTreeExpand(rows, expanded).then(() => {
handleVirtualTreeToList();
$xeTable.handleTableData();
reactData.treeExpandedFlag++;
updateAfterDataIndex();
return nextTick();
}).then(() => {
return handleRecalculateStyle(true, true, true);
}).then(() => {
restoreScrollLocation($xeTable, lastScrollLeft, lastScrollTop);
updateTreeLineStyle();
setTimeout(() => {
$xeTable.updateCellAreas();
}, 30);
});
};
/**
* 展开与收起行分组节点
* @param rows
* @param expanded
* @returns
*/
const handleRowGroupBaseExpand = (rows, expanded) => {
const { fullAllDataRowIdData, tableFullGroupData, rowGroupExpandedMaps } = internalData;
const aggregateOpts = computeAggregateOpts.value;
const { mapChildrenField, accordion } = aggregateOpts;
const { handleGetRowId } = createHandleGetRowId($xeTable);
let validRows = rows;
if (mapChildrenField) {
if (accordion) {
validRows = validRows.length ? [validRows[validRows.length - 1]] : [];
// 同一级只能展开一个
const matchObj = XEUtils.findTree(tableFullGroupData, item => getRowid($xeTable, item) === getRowid($xeTable, validRows[0]), { children: mapChildrenField });
if (matchObj) {
matchObj.items.forEach(item => {
const rowid = handleGetRowId(item);
if (rowGroupExpandedMaps[rowid]) {
delete rowGroupExpandedMaps[rowid];
}
});
}
}
if (expanded) {
validRows.forEach((row) => {
const rowid = handleGetRowId(row);
if (!rowGroupExpandedMaps[rowid]) {
const rowRest = fullAllDataRowIdData[rowid];
if (rowRest) {
if (row[mapChildrenField] && row[mapChildrenField].length) {
rowGroupExpandedMaps[rowid] = row;
}
}
}
});
}
else {
validRows.forEach(item => {
const rowid = handleGetRowId(item);
if (rowGroupExpandedMaps[rowid]) {
delete rowGroupExpandedMaps[rowid];
}
});
}
}
reactData.rowGroupExpandedFlag++;
return $xeTable.recalculate();
};
/**
* 行分组的展开与收起
* @param rows
* @param expanded
* @returns
*/
const handleRowGroupVirtualExpand = (rows, expanded) => {
return handleRowGroupBaseExpand(rows, expanded).then(() => {
handleVirtualTreeToList();
$xeTable.handleTableData();
reactData.rowGroupExpandedFlag++;
updateAfterDataIndex();
return nextTick();
}).then(() => {
return handleLazyRecalculate(true, true, true);
}).then(() => {
setTimeout(() => {
$xeTable.updateCellAreas();
}, 30);
});
};
/**
* 处理默认展开分组行
*/
const handleDefaultRowGroupExpand = () => {
const { isRowGroupStatus } = reactData;
if (isRowGroupStatus) {
const aggregateOpts = computeAggregateOpts.value;
const { expandAll, expandGroupFields } = aggregateOpts;
if (expandAll) {
$xeTable.setAllRowGroupExpand(true);
}
else if (expandGroupFields && expandGroupFields.length) {
$xeTable.setRowGroupExpandByField(expandGroupFields, true);
}
}
};
const handleCheckAllEvent = (evnt, value) => {
handleCheckedAllCheckboxRow(value);
if (evnt) {
dispatchEvent('checkbox-all', {
records: () => $xeTable.getCheckboxRecords(),
reserves: () => $xeTable.getCheckboxReserveRecords(),
indeterminates: () => $xeTable.getCheckboxIndeterminateRecords(),
checked: value
}, evnt);
}
};
/**
* 纵向 Y 可视渲染处理
*/
const loadScrollYData = () => {
const { isAllOverflow, isScrollYBig } = reactData;
const { mergeBodyList, mergeBodyColMaps, scrollYStore } = internalData;
const { preloadSize, startIndex, endIndex, offsetSize } = scrollYStore;
const autoOffsetYSize = isAllOverflow ? offsetSize : offsetSize + 1;
const { toVisibleIndex, visibleSize } = handleVirtualYVisible();
const offsetItem = {
startIndex: Math.max(0, isScrollYBig ? toVisibleIndex - 1 : toVisibleIndex - 1 - offsetSize - preloadSize),
endIndex: isScrollYBig ? (toVisibleIndex + visibleSize) : (toVisibleIndex + visibleSize + autoOffsetYSize + preloadSize)
};
scrollYStore.visibleStartIndex = toVisibleIndex - 1;
scrollYStore.visibleEndIndex = toVisibleIndex + visibleSize + 1;
calculateMergerOffsetIndex(mergeBodyList, mergeBodyColMaps, offsetItem, 'row');
const { startIndex: offsetStartIndex, endIndex: offsetEndIndex } = offsetItem;
if (toVisibleIndex <= startIndex || toVisibleIndex >= endIndex - visibleSize - 1) {
if (startIndex !== offsetStartIndex || endIndex !== offsetEndIndex) {
scrollYStore.startIndex = offsetStartIndex;
scrollYStore.endIndex = offsetEndIndex;
$xeTable.updateScrollYData();
}
}
};
const createGetRowCacheProp = (prop) => {
return function (row) {
const { fullAllDataRowIdData } = internalData;
if (row) {
const rowid = getRowid($xeTable, row);
const rowRest = fullAllDataRowIdData[rowid];
if (rowRest) {
return rowRest[prop];
}
}
return -1;
};
};
const createGetColumnCacheProp = (prop) => {
return function (column) {
const { fullColumnIdData } = internalData;
if (column) {
const colRest = fullColumnIdData[column.id];
if (colRest) {
return colRest[prop];
}
}
return -1;
};
};
const lazyScrollXData = () => {
const { lxTimeout, lxRunTime, scrollXStore } = internalData;
const { visibleSize } = scrollXStore;
const fpsTime = visibleSize > 26 ? 26 : (visibleSize > 16 ? 14 : 6);
if (lxTimeout) {
clearTimeout(lxTimeout);
}
if (!lxRunTime || lxRunTime + fpsTime < Date.now()) {
internalData.lxRunTime = Date.now();
loadScrollXData();
}
internalData.lxTimeout = setTimeout(() => {
internalData.lxTimeout = undefined;
internalData.lxRunTime = undefined;
loadScrollXData();
}, fpsTime);
};
const lazyScrollYData = () => {
const { lyTimeout, lyRunTime, scrollYStore } = internalData;
const { visibleSize } = scrollYStore;
const fpsTime = visibleSize > 30 ? 32 : (visibleSize > 20 ? 18 : 8);
if (lyTimeout) {
clearTimeout(lyTimeout);
}
if (!lyRunTime || lyRunTime + fpsTime < Date.now()) {
internalData.lyRunTime = Date.now();
loadScrollYData();
}
internalData.lyTimeout = setTimeout(() => {
internalData.lyTimeout = undefined;
internalData.lyRunTime = undefined;
loadScrollYData();
}, fpsTime);
};
const handleSyncScroll = (isRollX, isRollY) => {
const { scrollXLoad, scrollYLoad, isAllOverflow } = reactData;
const autoWidthColumnList = computeAutoWidthColumnList.value;
internalData.lcsRunTime = Date.now();
internalData.lcsTimeout = undefined;
internalData.intoRunScroll = false;
internalData.inVirtualScroll = false;
internalData.inWheelScroll = false;
internalData.inHeaderScroll = false;
internalData.inBodyScroll = false;
internalData.inFooterScroll = false;
reactData.lazScrollLoading = false;
internalData.scrollRenderType = '';
let xRest = null;
let yRest = null;
if (!isAllOverflow) {
calcCellHeight();
updateRowOffsetTop();
}
if (isRollX && scrollXLoad) {
xRest = $xeTable.updateScrollXData();
}
if (isRollY && scrollYLoad) {
if (autoWidthColumnList.length) {
calcCellWidth();
}
yRest = $xeTable.updateScrollYData().then(() => {
if (autoWidthColumnList.length) {
calcCellWidth();
autoCellWidth();
}
if (!isAllOverflow) {
calcCellHeight();
updateRowOffsetTop();
}
return $xeTable.updateScrollYSpace();
});
}
updateRowExpandStyle();
return Promise.all([
xRest,
yRest,
scrollXLoad || scrollYLoad ? $xeTable.updateCellAreas() : null
]);
};
const checkLastSyncScroll = (isRollX, isRollY) => {
const { lcsTimeout } = internalData;
reactData.lazScrollLoading = true;
if (lcsTimeout) {
clearTimeout(lcsTimeout);
}
internalData.lcsTimeout = setTimeout(() => {
handleSyncScroll(isRollX, isRollY).then(() => {
if (reactData.scrollXLoad || reactData.scrollYLoad) {
nextTick(() => {
updateRowExpandStyle();
if (!internalData.lcsTimeout) {
handleSyncScroll(isRollX, isRollY);
}
});
}
});
}, 240);
};
const getWheelSpeed = (lastScrollTime) => {
let multiple = 1;
const currTime = Date.now();
if (lastScrollTime + 25 > currTime) {
multiple = 1.18;
}
else if (lastScrollTime + 30 > currTime) {
multiple = 1.15;
}
else if (lastScrollTime + 40 > currTime) {
multiple = 1.12;
}
else if (lastScrollTime + 55 > currTime) {
multiple = 1.09;
}
else if (lastScrollTime + 75 > currTime) {
multiple = 1.06;
}
else if (lastScrollTime + 100 > currTime) {
multiple = 1.03;
}
return multiple;
};
const syncGanttScrollTop = (scrollTop) => {
const $xeGanttView = internalData.xeGanttView;
if ($xeGanttView) {
const ganttInternalData = $xeGanttView.internalData;
const { elemStore: ganttElemStore } = ganttInternalData;
const ganttBodyScrollElem = getRefElem(ganttElemStore['main-body-scroll']);
if (ganttBodyScrollElem) {
ganttBodyScrollElem.scrollTop = scrollTop;
}
}
};
const dispatchEvent = (type, params, evnt) => {
emit(type, createEvent(evnt, { $table: $xeTable, $grid: $xeGrid, $gantt: $xeGantt }, params));
};
const handleScrollToRowColumn = (fieldOrColumn, row, options) => {
const { fullColumnIdData } = internalData;
const column = handleFieldOrColumn($xeTable, fieldOrColumn);
if (column && fullColumnIdData[column.id]) {
return colToVisible($xeTable, options ? options.colAlign !== false : true, column, row);
}
return nextTick();
};
const handleUpdateResize = () => {
const el = refElem.value;
if (el && el.clientWidth && el.clientHeight) {
$xeTable.recalculate();
}
};
const handleUpdateColResize = (evnt, params) => {
$xeTable.analyColumnWidth();
$xeTable.recalculate().then(() => {
$xeTable.saveCustomStore('update:width');
$xeTable.refreshScroll().then(() => {
$xeTable.updateCellAreas();
});
$xeTable.dispatchEvent('column-resizable-change', params, evnt);
// 已废弃 resizable-change
$xeTable.dispatchEvent('resizable-change', params, evnt);
setTimeout(() => {
$xeTable.recalculate(true);
}, 300);
});
};
const handleUpdateRowResize = (evnt, params) => {
reactData.resizeHeightFlag++;
$xeTable.recalculate().then(() => {
$xeTable.refreshScroll().then(() => {
$xeTable.updateCellAreas();
});
$xeTable.dispatchEvent('row-resizable-change', params, evnt);
setTimeout(() => {
$xeTable.recalculate(true);
}, 300);
});
};
const updateColumnOffsetLeft = () => {
const { visibleColumn, fullColumnIdData } = internalData;
const el = refElem.value;
if (!el || !el.clientWidth) {
return;
}
let offsetLeft = 0;
for (let cIndex = 0, rLen = visibleColumn.length; cIndex < rLen; cIndex++) {
const column = visibleColumn[cIndex];
const colid = column.id;
const colRest = fullColumnIdData[colid];
if (colRest) {
colRest.oLeft = offsetLeft;
}
offsetLeft += column.renderWidth;
}
};
const updateRowOffsetTop = () => {
const { expandColumn } = reactData;
const { afterFullData, fullAllDataRowIdData, rowExpandedMaps } = internalData;
const el = refElem.value;
if (!el || !el.clientWidth) {
return;
}
const expandOpts = computeExpandOpts.value;
const rowOpts = computeRowOpts.value;
const cellOpts = computeCellOpts.value;
const defaultRowHeight = computeDefaultRowHeight.value;
const { handleGetRowId } = createHandleGetRowId($xeTable);
let offsetTop = 0;
for (let rIndex = 0, rLen = afterFullData.length; rIndex < rLen; rIndex++) {
const row = afterFullData[rIndex];
const rowid = handleGetRowId(row);
const rowRest = fullAllDataRowIdData[rowid] || {};
rowRest.oTop = offsetTop;
offsetTop += getCellRestHeight(rowRest, cellOpts, rowOpts, defaultRowHeight);
// 是否展开行
if (expandColumn && rowExpandedMaps[rowid]) {
offsetTop += rowRest.expandHeight || expandOpts.height || 0;
}
}
};
/**
* 更新展开行样式
*/
const updateRowExpandStyle = () => {
const { expandColumn, scrollYLoad, scrollYTop, isScrollYBig } = reactData;
const el = refElem.value;
if (!el || !el.clientWidth) {
return;
}
const expandOpts = computeExpandOpts.value;
const { mode } = expandOpts;
if (expandColumn && mode === 'fixed') {
const { elemStore, fullAllDataRowIdData } = internalData;
const rowOpts = computeRowOpts.value;
const cellOpts = computeCellOpts.value;
const defaultRowHeight = computeDefaultRowHeight.value;
const rowExpandEl = refRowExpandElem.value;
const bodyScrollElem = getRefElem(elemStore['main-body-scroll']);
if (rowExpandEl && bodyScrollElem) {
let isUpdateHeight = false;
XEUtils.arrayEach(rowExpandEl.children, reEl => {
const expandEl = reEl;
const rowid = expandEl.getAttribute('rowid') || '';
const rowRest = fullAllDataRowIdData[rowid];
if (rowRest) {
const expandHeight = expandEl.offsetHeight;
const trEl = bodyScrollElem.querySelector(`.vxe-body--row[rowid="${rowid}"]`);
let offsetTop = 0;
if (scrollYLoad) {
if (isScrollYBig && trEl) {
offsetTop = trEl.offsetTop + trEl.offsetHeight;
}
else {
offsetTop = rowRest.oTop + getCellRestHeight(rowRest, cellOpts, rowOpts, defaultRowHeight);
}
}
else {
if (trEl) {
offsetTop = trEl.offsetTop + trEl.offsetHeight;
}
}
if (isScrollYBig) {
offsetTop += scrollYTop;
}
expandEl.style.top = toCssUnit(offsetTop);
if (!isUpdateHeight) {
if (rowRest.expandHeight !== expandHeight) {
isUpdateHeight = true;
}
}
rowRest.expandHeight = expandHeight;
}
});
if (isUpdateHeight) {
reactData.rowExpandHeightFlag++;
nextTick(() => {
updateRowOffsetTop();
});
}
}
}
};
/**
* 更新树连接线样式
*/
const updateTreeLineStyle = () => {
const { treeConfig } = props;
if (!treeConfig) {
return;
}
const { tableData } = reactData;
const { fullAllDataRowIdData, treeExpandedMaps } = internalData;
const el = refElem.value;
if (!el || !el.clientWidth) {
return;
}
const cellOpts = computeCellOpts.value;
const rowOpts = computeRowOpts.value;
const defaultRowHeight = computeDefaultRowHeight.value;
const treeOpts = computeTreeOpts.value;
const { transform, mapChildrenField } = treeOpts;
const childrenField = treeOpts.children || treeOpts.childrenField;
const { handleGetRowId } = createHandleGetRowId($xeTable);
const expParentList = [];
const handleNodeRow = (row, rIndex, rows) => {
const rowid = handleGetRowId(row);
const rowRest = fullAllDataRowIdData[rowid] || {};
const childList = row[transform ? mapChildrenField : childrenField];
const prevRow = rows[rIndex - 1] || null;
const nextRow = rows[rIndex + 1] || null;
if (childList && childList.length && treeExpandedMaps[rowid]) {
expParentList.push({ row, prevRow, nextRow });
childList.forEach((childRow, crIndex) => {
const childRowid = handleGetRowId(childRow);
if (treeExpandedMaps[childRowid]) {
handleNodeRow(childRow, crIndex, childList);
}
});
}
else {
if (nextRow) {
const nextRowid = handleGetRowId(nextRow);
const nextRowRest = fullAllDataRowIdData[nextRowid] || {};
const currCellHeight = getCellRestHeight(rowRest, cellOpts, rowOpts, defaultRowHeight);
const nextCellHeight = getCellRestHeight(nextRowRest, cellOpts, rowOpts, defaultRowHeight);
rowRest.oHeight = currCellHeight;
rowRest.lineHeight = Math.floor(currCellHeight / 2 + nextCellHeight / 2);
}
else {
rowRest.oHeight = 0;
rowRest.lineHeight = 0;
}
}
};
tableData.forEach((row, rIndex) => {
handleNodeRow(row, rIndex, tableData);
});
XEUtils.lastArrayEach(expParentList, ({ row, nextRow }) => {
const rowid = handleGetRowId(row);
const childList = row[transform ? mapChildrenField : childrenField];
const rowRest = fullAllDataRowIdData[rowid];
if (rowRest) {
const currCellHeight = getCellRestHeight(rowRest, cellOpts, rowOpts, defaultRowHeight);
let countOffsetHeight = currCellHeight;
let countLineHeight = 0;
childList.forEach((childRow) => {
const childRowid = handleGetRowId(childRow);
const childRowRest = fullAllDataRowIdData[childRowid] || {};
const childList = childRow[transform ? mapChildrenField : childrenField];
if (treeExpandedMaps[childRowid] && childList && childList.length) {
countOffsetHeight += (childRowRest.oHeight || 0);
countLineHeight += (childRowRest.oHeight || 0);
}
else {
const cellHeight = getCellRestHeight(childRowRest, cellOpts, rowOpts, defaultRowHeight);
childRowRest.oHeight = cellHeight;
childRowRest.lineHeight = cellHeight;
countOffsetHeight += cellHeight;
countLineHeight += cellHeight;
}
});
if (nextRow) {
const nextRowid = handleGetRowId(nextRow);
const nextRowRest = fullAllDataRowIdData[nextRowid] || {};
const currCellHeight = getCellRestHeight(rowRest, cellOpts, rowOpts, defaultRowHeight);
const nextCellHeight = getCellRestHeight(nextRowRest, cellOpts, rowOpts, defaultRowHeight);
countOffsetHeight += currCellHeight;
countLineHeight += Math.floor(currCellHeight / 2 + nextCellHeight / 2);
}
rowRest.lineHeight = countLineHeight;
rowRest.oHeight = countOffsetHeight;
}
});
};
const handleRowExpandScroll = () => {
const { elemStore } = internalData;
const rowExpandEl = refRowExpandElem.value;
const bodyScrollElem = getRefElem(elemStore['main-body-scroll']);
if (rowExpandEl && bodyScrollElem) {
rowExpandEl.scrollTop = bodyScrollElem.scrollTop;
}
};
const handleColumnVisible = (visible) => {
return function (fieldOrColumn) {
let status = false;
const cols = XEUtils.isArray(fieldOrColumn) ? fieldOrColumn : [fieldOrColumn];
cols.forEach(item => {
const column = handleFieldOrColumn($xeTable, item);
if (column) {
if (column.children && column.children.length) {
XEUtils.eachTree([column], (item) => {
item.visible = visible;
item.renderVisible = visible;
});
}
else {
column.visible = visible;
column.renderVisible = visible;
}
if (!status) {
status = true;
}
}
});
if (status) {
return $xeTable.handleCustom();
}
return nextTick();
};
};
tableMethods = {
dispatchEvent,
getEl() {
return refElem.value;
},
/**
* 重置表格的一切数据状态
*/
clearAll() {
return clearTableAllStatus($xeTable);
},
/**
* 同步 data 数据(即将废弃)
* 如果用了该方法,那么组件将不再记录增删改的状态,只能自行实现对应逻辑
* 对于某些特殊的场景,比如深层树节点元素发生变动时可能会用到
*/
syncData() {
errLog('vxe.error.delFunc', ['syncData', 'getData']);
return nextTick().then(() => {
reactData.tableData = [];
emit('update:data', internalData.tableFullData);
return nextTick();
});
},
/**
* 手动处理数据,用于手动排序与筛选
* 对于手动更改了排序、筛选...等条件后需要重新处理数据时可能会用到
*/
updateData() {
const { scrollXLoad, scrollYLoad } = reactData;
return $xeTable.handleTableData(true).then(() => {
$xeTable.updateFooter();
if (scrollXLoad || scrollYLoad) {
if (scrollXLoad) {
$xeTable.updateScrollXSpace();
}
if (scrollYLoad) {
$xeTable.updateScrollYSpace();
}
return $xeTable.refreshScroll();
}
}).then(() => {
$xeTable.updateCellAreas();
return handleLazyRecalculate(true, true, true);
}).then(() => {
// 存在滚动行为未结束情况
setTimeout(() => handleLazyRecalculate(false, true, true), 50);
});
},
/**
* 重新加载数据,不会清空表格状态
* @param {Array} datas 数据
*/
loadData(datas) {
const { initStatus } = internalData;
return loadTableData(datas, false, false).then(() => {
internalData.inited = true;
internalData.initStatus = true;
if (!initStatus) {
handleLoadDefaults();
}
return handleLazyRecalculate(false, true, true);
});
},
/**
* 重新加载数据,会清空表格状态
* @param {Array} datas 数据
*/
reloadData(datas) {
return $xeTable.clearAll()
.then(() => {
internalData.inited = true;
internalData.initStatus = true;
return loadTableData(datas, true, true);
}).then(() => {
handleLoadDefaults();
return handleLazyRecalculate(false, true, true);
});
},
/**
* 修改行数据
*/
setRow(rows, record) {
if (rows && record) {
let rest = rows;
if (!XEUtils.isArray(rows)) {
rest = [rows];
}
const rowkey = getRowkey($xeTable);
rest.forEach(row => {
const rowid = getRowid($xeTable, row);
const newRecord = XEUtils.clone(Object.assign({}, record), true);
XEUtils.set(newRecord, rowkey, rowid);
Object.assign(row, newRecord);
});
}
return nextTick();
},
/**
* 局部加载行数据并恢复到初始状态
* 对于行数据需要局部更改的场景中可能会用到
* @param {Row} row 行对象
* @param {Object} record 新数据
* @param {String} field 字段名
*/
reloadRow(row, record, field) {
const { keepSource } = props;
const { tableData } = reactData;
const { sourceDataRowIdData } = internalData;
if (keepSource) {
if ($xeTable.isAggregateRecord(row)) {
return nextTick();
}
const rowkey = getRowkey($xeTable);
const rowid = XEUtils.get(row, rowkey);
const oRow = sourceDataRowIdData[rowid];
if (oRow && row) {
if (field) {
const newValue = XEUtils.clone(XEUtils.get(record || row, field), true);
XEUtils.set(row, field, newValue);
XEUtils.set(oRow, field, newValue);
}
else {
const newRecord = XEUtils.clone(Object.assign({}, record), true);
XEUtils.set(newRecord, rowkey, rowid);
XEUtils.destructuring(oRow, Object.assign(row, newRecord));
}
}
reactData.tableData = tableData.slice(0);
}
else {
errLog('vxe.error.reqProp', ['keep-source']);
}
return nextTick();
},
getParams() {
return props.params;
},
/**
* 用于树结构,给行数据加载子节点
*/
loadTreeChildren(row, childRecords) {
const { keepSource } = props;
const { tableSourceData, fullDataRowIdData, fullAllDataRowIdData, sourceDataRowIdData } = internalData;
const treeOpts = computeTreeOpts.value;
const { transform, mapChildrenField } = treeOpts;
const childrenField = treeOpts.children || treeOpts.childrenField;
const parentRest = fullAllDataRowIdData[getRowid($xeTable, row)];
const parentLevel = parentRest ? parentRest.level : 0;
return $xeTable.createData(childRecords).then((rows) => {
if (keepSource) {
const rowid = getRowid($xeTable, row);
const matchObj = XEUtils.findTree(tableSourceData, (item) => rowid === getRowid($xeTable, item), { children: childrenField });
if (matchObj) {
matchObj.item[childrenField] = XEUtils.clone(rows, true);
}
rows.forEach(childRow => {
const rowid = getRowid($xeTable, childRow);
sourceDataRowIdData[rowid] = XEUtils.clone(childRow, true);
});
}
XEUtils.eachTree(rows, (childRow, index, items, path, parentItem, nodes) => {
const rowid = getRowid($xeTable, childRow);
const parentRow = parentItem || parentRest.row;
const rest = { row: childRow, rowid, _seq: -1, seq: -1, index, _index: -1, $index: -1, treeIndex: -1, _tIndex: -1, items, parent: parentRow, level: parentLevel + nodes.length, height: 0, resizeHeight: 0, oTop: 0, expandHeight: 0 };
fullDataRowIdData[rowid] = rest;
fullAllDataRowIdData[rowid] = rest;
}, { children: childrenField });
row[childrenField] = rows;
if (transform) {
row[mapChildrenField] = XEUtils.clone(rows, false);
}
updateAfterDataIndex();
return rows;
});
},
/**
* 加载列配置
* 对于表格列需要重载、局部递增场景下可能会用到
* @param {ColumnInfo} columns 列配置
*/
loadColumn(columns) {
const { lastScrollLeft, lastScrollTop } = internalData;
const collectColumn = XEUtils.mapTree(columns, column => reactive(Cell.createColumn($xeTable, column)));
return handleInitColumn(collectColumn).then(() => {
let targetScrollLeft = lastScrollLeft;
let targetScrollTop = lastScrollTop;
const virtualXOpts = computeVirtualXOpts.value;
const virtualYOpts = computeVirtualYOpts.value;
// 是否在更新数据之后自动滚动重置滚动条
if (virtualXOpts.scrollToLeftOnChange) {
targetScrollLeft = 0;
}
if (virtualYOpts.scrollToTopOnChange) {
targetScrollTop = 0;
}
restoreScrollLocation($xeTable, targetScrollLeft, targetScrollTop);
});
},
/**
* 加载列配置并恢复到初始状态
* 对于表格列需要重载、局部递增场景下可能会用到
* @param {ColumnInfo} columns 列配置
*/
reloadColumn(columns) {
return $xeTable.clearAll().then(() => {
return $xeTable.loadColumn(columns);
});
},
/**
* 根据 tr 元素获取对应的 row 信息
* @param {Element} tr 元素
*/
getRowNode(tr) {
if (tr) {
const { fullAllDataRowIdData } = internalData;
const rowid = tr.getAttribute('rowid');
if (rowid) {
const rowRest = fullAllDataRowIdData[rowid];
if (rowRest) {
return {
rowid: rowRest.rowid,
item: rowRest.row,
index: rowRest.index,
items: rowRest.items,
parent: rowRest.parent
};
}
}
}
return null;
},
/**
* 根据 th/td 元素获取对应的 column 信息
* @param {Element} cell 元素
*/
getColumnNode(cell) {
if (cell) {
const { fullColumnIdData } = internalData;
const colid = cell.getAttribute('colid');
if (colid) {
const colRest = fullColumnIdData[colid];
if (colRest) {
return {
colid: colRest.colid,
item: colRest.column,
index: colRest.index,
items: colRest.items,
parent: colRest.parent
};
}
}
}
return null;
},
/**
* 根据 row 获取序号
* @param {Row} row 行对象
*/
getRowSeq: createGetRowCacheProp('seq'),
/**
* 根据 row 获取相对于 data 中的索引
* @param {Row} row 行对象
*/
getRowIndex: createGetRowCacheProp('index'),
/**
* 根据 row 获取相对于当前数据中的索引
* @param {Row} row 行对象
*/
getVTRowIndex: createGetRowCacheProp('_index'),
/**
* 根据 row 获取渲染中的虚拟索引
* @param {Row} row 行对象
*/
getVMRowIndex: createGetRowCacheProp('$index'),
/**
* 根据 column 获取相对于 columns 中的索引
* @param {ColumnInfo} column 列配置
*/
getColumnIndex: createGetColumnCacheProp('index'),
/**
* 根据 column 获取相对于当前表格列中的索引
* @param {ColumnInfo} column 列配置
*/
getVTColumnIndex: createGetColumnCacheProp('_index'),
/**
* 根据 column 获取渲染中的虚拟索引
* @param {ColumnInfo} column 列配置
*/
getVMColumnIndex: createGetColumnCacheProp('$index'),
/**
* 创建 data 对象
* 对于某些特殊场景可能会用到,会自动对数据的字段名进行检测,如果不存在就自动定义
* @param {Array} records 新数据
*/
createData(records) {
return nextTick().then(() => {
return reactive($xeTable.defineField(records));
});
},
/**
* 创建 Row|Rows 对象
* 对于某些特殊场景需要对数据进行手动插入时可能会用到
* @param {Array/Object} records 新数据
*/
createRow(records) {
const isArr = XEUtils.isArray(records);
if (!isArr) {
records = [records || {}];
}
return $xeTable.createData(records).then((rows) => isArr ? rows : rows[0]);
},
/**
* 还原数据
* 如果不传任何参数,则还原整个表格
* 如果传 row 则还原一行
* 如果传 rows 则还原多行
* 如果还额外传了 field 则还原指定的单元格数据
*/
revertData(rows, field) {
const { keepSource, treeConfig } = props;
const { fullAllDataRowIdData, fullDataRowIdData, tableSourceData, sourceDataRowIdData, tableFullData, afterFullData, removeRowMaps } = internalData;
const treeOpts = computeTreeOpts.value;
const { transform } = treeOpts;
const { handleGetRowId } = createHandleGetRowId($xeTable);
if (!keepSource) {
errLog('vxe.error.reqProp', ['keep-source']);
return nextTick();
}
let targetRows = rows;
if (rows) {
if (!XEUtils.isArray(rows)) {
targetRows = [rows];
}
}
else {
targetRows = XEUtils.toArray($xeTable.getUpdateRecords());
}
let reDelFlag = false;
if (targetRows.length) {
targetRows.forEach((item) => {
const rowid = handleGetRowId(item);
const rowRest = fullAllDataRowIdData[rowid];
if (rowRest) {
const row = rowRest.row;
if (!$xeTable.isInsertByRow(row)) {
const oRow = sourceDataRowIdData[rowid];
if (oRow && row) {
if (field) {
XEUtils.set(row, field, XEUtils.clone(XEUtils.get(oRow, field), true));
}
else {
XEUtils.destructuring(row, XEUtils.clone(oRow, true));
}
if (!fullDataRowIdData[rowid] && $xeTable.isRemoveByRow(row)) {
if (removeRowMaps[rowid]) {
delete removeRowMaps[rowid];
}
tableFullData.unshift(row);
afterFullData.unshift(row);
reDelFlag = true;
}
}
}
}
});
}
if (rows) {
if (reDelFlag) {
reactData.removeRowFlag++;
$xeTable.updateFooter();
$xeTable.cacheRowMap(false);
$xeTable.handleTableData(treeConfig && transform);
if (!(treeConfig && transform)) {
$xeTable.updateAfterDataIndex();
}
$xeTable.checkSelectionStatus();
if (reactData.scrollYLoad) {
$xeTable.updateScrollYSpace();
}
}
return nextTick().then(() => {
$xeTable.updateCellAreas();
return handleLazyRecalculate(false, true, true);
});
}
return $xeTable.reloadData(tableSourceData);
},
/**
* 清空单元格内容
* 如果不创参数,则清空整个表格内容
* 如果传 row 则清空一行内容
* 如果传 rows 则清空多行内容
* 如果还额外传了 field 则清空指定单元格内容
* @param {Array/Row} rows 行数据
* @param {String} field 字段名
*/
clearData(rows, field) {
const { tableFullData, visibleColumn } = internalData;
if (!arguments.length) {
rows = tableFullData;
}
else if (rows && !XEUtils.isArray(rows)) {
rows = [rows];
}
if (field) {
rows.forEach((row) => XEUtils.set(row, field, null));
}
else {
rows.forEach((row) => {
visibleColumn.forEach((column) => {
if (column.field) {
setCellValue(row, column, null);
}
});
});
}
return nextTick();
},
effectCellData(row, column, options) {
const { fullCellStoreMaps } = internalData;
const editOpts = computeEditOpts.value;
const { key, isChanged, setValue, getResult } = options;
const rowid = getRowid($xeTable, row);
const colid = column.id;
let rowStore = fullCellStoreMaps[rowid];
const cellValue = XEUtils.get(row, column.field);
const restParams = {
$table: $xeTable,
row,
rowid,
column,
colid,
cellValue,
oldValue: null
};
if (editOpts.cache === false && key === 'render_table_cell') {
const rest = restParams;
rest.cellResult = getResult ? getResult(restParams) : cellValue;
return rest;
}
if (!rowStore) {
rowStore = {};
fullCellStoreMaps[rowid] = rowStore;
}
let cellStore = rowStore[colid];
if (!cellStore) {
cellStore = {
value: undefined,
result: {}
};
rowStore[colid] = cellStore;
}
const restData = rowStore[colid];
const oldValue = restData.value;
restParams.oldValue = oldValue;
if (isChanged ? !isChanged(restParams) : oldValue !== cellValue) {
restData.value = setValue ? setValue(restParams) : cellValue;
restData.result = {};
}
const storeData = restData.result;
if (XEUtils.isUndefined(storeData[key])) {
storeData[key] = getResult ? getResult(restParams) : cellValue;
}
const cellResult = storeData[key];
const rest = restParams;
rest.cellResult = cellResult;
return rest;
},
getCellElement(row, fieldOrColumn) {
const { elemStore } = internalData;
const column = handleFieldOrColumn($xeTable, fieldOrColumn);
if (!column) {
return null;
}
const rowid = getRowid($xeTable, row);
const bodyScrollElem = getRefElem(elemStore['main-body-scroll']);
const leftScrollElem = getRefElem(elemStore['left-body-scroll']);
const rightScrollElem = getRefElem(elemStore['right-body-scroll']);
let bodyElem;
if (column) {
if (column.fixed) {
if (column.fixed === 'left') {
if (leftScrollElem) {
bodyElem = leftScrollElem;
}
}
else {
if (rightScrollElem) {
bodyElem = rightScrollElem;
}
}
}
if (!bodyElem) {
bodyElem = bodyScrollElem;
}
if (bodyElem) {
return bodyElem.querySelector(`.vxe-body--row[rowid="${rowid}"] .${column.id}`);
}
}
return null;
},
getCellLabel(row, fieldOrColumn) {
const column = handleFieldOrColumn($xeTable, fieldOrColumn);
if (!column) {
return null;
}
const { editConfig } = props;
const { formatter, editRender, cellRender } = column;
let etOpSize = null;
let etOgSize = null;
let clOpSize = null;
let clOgSize = null;
if (editRender) {
etOpSize = editRender.options ? editRender.options.length : 0;
etOgSize = editRender.optionGroups ? editRender.optionGroups.length : 0;
}
if (cellRender) {
clOpSize = cellRender.options ? cellRender.options.length : 0;
clOgSize = cellRender.optionGroups ? cellRender.optionGroups.length : 0;
}
// formatter > tableCellFormatter
const renderOpts = formatter ? null : (editConfig && isEnableConf(editRender) ? editRender : (isEnableConf(cellRender) ? cellRender : null));
const compConf = renderOpts ? renderer.get(renderOpts.name) : null;
const tcFormatter = compConf ? compConf.tableCellFormatter : null;
const cellValue = getCellValue(row, column);
let cellLabel = cellValue;
if (formatter || tcFormatter) {
let formatData;
const { fullAllDataRowIdData } = internalData;
const rowid = getRowid($xeTable, row);
const colid = column.id;
const rowRest = fullAllDataRowIdData[rowid];
if (rowRest) {
formatData = rowRest.formatData;
if (!formatData) {
formatData = fullAllDataRowIdData[rowid].formatData = {};
}
if (rowRest && formatData[colid]) {
const ftValue = formatData[colid].value;
if (ftValue && ftValue[0] === cellValue && ftValue[1] === etOpSize && ftValue[2] === etOgSize && ftValue[3] === clOpSize && ftValue[4] === clOgSize) {
return formatData[colid].label;
}
}
}
const formatParams = {
$table: $xeTable,
cellValue,
row,
rowIndex: $xeTable.getRowIndex(row),
column,
columnIndex: $xeTable.getColumnIndex(column)
};
if (formatter) {
if (XEUtils.isString(formatter)) {
const gFormatOpts = formats.get(formatter);
const tcFormatMethod = gFormatOpts ? (gFormatOpts.tableCellFormatMethod || gFormatOpts.cellFormatMethod) : null;
cellLabel = tcFormatMethod ? tcFormatMethod(formatParams) : '';
}
else if (XEUtils.isArray(formatter)) {
const gFormatOpts = formats.get(formatter[0]);
const tcFormatMethod = gFormatOpts ? (gFormatOpts.tableCellFormatMethod || gFormatOpts.cellFormatMethod) : null;
cellLabel = tcFormatMethod ? tcFormatMethod(formatParams, ...formatter.slice(1)) : '';
}
else {
cellLabel = formatter(formatParams);
}
}
else if (renderOpts && tcFormatter) {
cellLabel = tcFormatter(renderOpts, formatParams);
}
if (formatData) {
const ftValue = [cellValue, etOpSize, etOgSize, clOpSize, clOgSize];
formatData[colid] = { value: ftValue, label: cellLabel };
}
}
return cellLabel;
},
updateCellLabel(row, fieldOrColumn) {
const column = handleFieldOrColumn($xeTable, fieldOrColumn);
if (!column) {
return null;
}
const { fullAllDataRowIdData } = internalData;
const rowid = getRowid($xeTable, row);
if (rowid) {
const colid = column.id;
const rowid = getRowid($xeTable, row);
const rowRest = fullAllDataRowIdData[rowid];
if (rowRest) {
const formatData = rowRest.formatData;
if (formatData) {
delete formatData[colid];
}
}
}
return $xeTable.getFooterCellLabel(row, column);
},
clearFormatterCache(isUpdate) {
const { tableData, tableColumn } = reactData;
const { fullAllDataRowIdData } = internalData;
XEUtils.each(fullAllDataRowIdData, (rowRest) => {
if (rowRest.formatData) {
rowRest.formatData = undefined;
}
});
if (isUpdate) {
tableData.forEach(row => {
tableColumn.forEach(column => {
$xeTable.getCellLabel(row, column);
});
});
}
return nextTick();
},
getHeaderCellLabel(fieldOrColumn) {
const column = handleFieldOrColumn($xeTable, fieldOrColumn);
if (!column) {
return null;
}
const { headerFormatter } = column;
const _columnIndex = $xeTable.getVTColumnIndex(column);
let cellLabel = column.getTitle();
if (headerFormatter) {
let formatData;
const { headerFullDataColData } = internalData;
const colid = column.id;
let colRest = headerFullDataColData[colid];
if (!colRest) {
colRest = headerFullDataColData[colid] = {};
}
const formatObj = colRest.formatObj;
if (formatObj && formatObj.value === cellLabel) {
return formatObj.label;
}
const headFormatParams = {
$table: $xeTable,
cellTitle: cellLabel,
cellValue: cellLabel,
column,
_columnIndex,
columnIndex: $xeTable.getColumnIndex(column)
};
if (XEUtils.isString(headerFormatter)) {
const gFormatOpts = formats.get(headerFormatter);
const fcFormatMethod = gFormatOpts ? gFormatOpts.tableHeaderCellFormatMethod : null;
cellLabel = XEUtils.toValueString(fcFormatMethod ? fcFormatMethod(headFormatParams) : '');
}
else if (XEUtils.isArray(headerFormatter)) {
const gFormatOpts = formats.get(headerFormatter[0]);
const fcFormatMethod = gFormatOpts ? gFormatOpts.tableHeaderCellFormatMethod : null;
cellLabel = XEUtils.toValueString(fcFormatMethod ? fcFormatMethod(headFormatParams, ...headerFormatter.slice(1)) : '');
}
else {
cellLabel = XEUtils.toValueString(headerFormatter(headFormatParams));
}
if (formatData) {
colRest.formatObj = { value: cellLabel, label: cellLabel };
}
}
return cellLabel;
},
updateHeaderCellLabel(fieldOrColumn) {
const column = handleFieldOrColumn($xeTable, fieldOrColumn);
if (!column) {
return '';
}
const { headerFullDataColData } = internalData;
const colid = column.id;
const colRest = headerFullDataColData[colid];
if (colRest) {
colRest.formatObj = undefined;
}
return $xeTable.getHeaderCellLabel(column);
},
clearHeaderFormatterCache(isUpdate) {
const { tableColumn } = reactData;
const { headerFullDataColData } = internalData;
XEUtils.each(headerFullDataColData, (colRest) => {
if (colRest.formatObj) {
colRest.formatObj = undefined;
}
});
if (isUpdate) {
tableColumn.forEach(column => {
$xeTable.getHeaderCellLabel(column);
});
}
return nextTick();
},
getFooterCellLabel(row, fieldOrColumn) {
const column = handleFieldOrColumn($xeTable, fieldOrColumn);
if (!column) {
return null;
}
const { footerFormatter } = column;
const _columnIndex = $xeTable.getVTColumnIndex(column);
let itemValue = '';
// 兼容老模式
if (XEUtils.isArray(row)) {
itemValue = row[_columnIndex];
}
else {
itemValue = XEUtils.get(row, column.field);
}
let cellLabel = itemValue;
if (footerFormatter) {
let formatData;
const { footerTableData } = reactData;
const { footerFullDataRowData } = internalData;
const colid = column.id;
const $rowIndex = footerTableData.indexOf(row);
let rowRest = null;
if ($rowIndex > -1) {
rowRest = footerFullDataRowData[$rowIndex];
if (!rowRest) {
rowRest = footerFullDataRowData[$rowIndex] = {};
}
formatData = rowRest.formatData;
if (!formatData) {
formatData = footerFullDataRowData[$rowIndex].formatData = {};
}
if (rowRest && formatData[colid]) {
if (formatData[colid].value === itemValue) {
return formatData[colid].label;
}
}
}
const footerFormatParams = {
$table: $xeTable,
cellValue: itemValue,
itemValue,
row,
items: row,
$rowIndex,
column,
_columnIndex,
columnIndex: $xeTable.getColumnIndex(column)
};
if (XEUtils.isString(footerFormatter)) {
const gFormatOpts = formats.get(footerFormatter);
const fcFormatMethod = gFormatOpts ? gFormatOpts.tableFooterCellFormatMethod : null;
cellLabel = fcFormatMethod ? fcFormatMethod(footerFormatParams) : '';
}
else if (XEUtils.isArray(footerFormatter)) {
const gFormatOpts = formats.get(footerFormatter[0]);
const fcFormatMethod = gFormatOpts ? gFormatOpts.tableFooterCellFormatMethod : null;
cellLabel = fcFormatMethod ? fcFormatMethod(footerFormatParams, ...footerFormatter.slice(1)) : '';
}
else {
cellLabel = footerFormatter(footerFormatParams);
}
if (formatData) {
formatData[colid] = { value: itemValue, label: cellLabel };
}
}
return cellLabel;
},
updateFooterCellLabel(row, fieldOrColumn) {
const column = handleFieldOrColumn($xeTable, fieldOrColumn);
if (!column) {
return null;
}
const { footerTableData } = reactData;
const { footerFullDataRowData } = internalData;
const colid = column.id;
const $rowIndex = footerTableData.indexOf(row);
const rowRest = footerFullDataRowData[$rowIndex];
if (rowRest) {
const formatData = rowRest.formatData;
if (formatData) {
delete formatData[colid];
}
}
return $xeTable.getFooterCellLabel(row, column);
},
clearFooterFormatterCache(isUpdate) {
const { tableData, tableColumn } = reactData;
const { footerFullDataRowData } = internalData;
XEUtils.each(footerFullDataRowData, (rowRest) => {
if (rowRest.formatData) {
rowRest.formatData = undefined;
}
});
if (isUpdate) {
tableData.forEach(row => {
tableColumn.forEach(column => {
$xeTable.getFooterCellLabel(row, column);
});
});
}
return nextTick();
},
/**
* 检查是否为临时行数据
*/
isInsertByRow(row) {
const rowid = getRowid($xeTable, row);
return !!reactData.insertRowFlag && !!internalData.insertRowMaps[rowid];
},
isRemoveByRow(row) {
const rowid = getRowid($xeTable, row);
return !!reactData.removeRowFlag && !!internalData.removeRowMaps[rowid];
},
/**
* 删除所有新增的临时数据
*/
removeInsertRow() {
const { insertRowMaps } = internalData;
return $xeTable.remove(XEUtils.values(insertRowMaps));
},
/**
* 检查行或列数据是否发生改变
*/
isUpdateByRow(rowidOrRow, field) {
const { keepSource } = props;
const { fullDataRowIdData, sourceDataRowIdData } = internalData;
const keepFields = computeKeepFields.value;
if (keepSource) {
const rowid = XEUtils.isString(rowidOrRow) || XEUtils.isNumber(rowidOrRow) ? rowidOrRow : getRowid($xeTable, rowidOrRow);
const rowRest = fullDataRowIdData[rowid];
// 新增的数据不需要检测
if (!rowRest) {
return false;
}
const row = rowRest.row;
const oRow = sourceDataRowIdData[rowid];
if (!oRow) {
return false;
}
if (arguments.length > 1) {
return !eqCellValue(row, oRow, field).result;
}
for (let i = 0; i < keepFields.length; i++) {
if (!eqCellValue(row, oRow, keepFields[i]).result) {
return true;
}
}
}
return false;
},
getUpdateCells() {
const { keepSource, treeConfig } = props;
const { tableFullData, tableFullTreeData, fullDataRowIdData, sourceDataRowIdData, fullColumnFieldData } = internalData;
const treeOpts = computeTreeOpts.value;
const keepFields = computeKeepFields.value;
const cellList = [];
if (keepSource) {
const { handleGetRowId } = createHandleGetRowId($xeTable);
const handleCell = (item) => {
const rowid = handleGetRowId(item);
const rowRest = fullDataRowIdData[rowid];
// 新增的数据不需要检测
if (!rowRest) {
return;
}
const row = rowRest.row;
const oRow = sourceDataRowIdData[rowid];
if (!oRow) {
return;
}
for (let i = 0; i < keepFields.length; i++) {
const field = keepFields[i];
const { result, newValue, oldValue } = eqCellValue(row, oRow, field);
if (!result) {
const column = fullColumnFieldData[field] ? fullColumnFieldData[field].column : null;
cellList.push({ row, rowid, column, field, newValue, oldValue });
}
}
};
if (treeConfig) {
XEUtils.eachTree(tableFullTreeData, handleCell, treeOpts);
}
else {
tableFullData.forEach(handleCell);
}
}
return cellList;
},
/**
* 获取表格的可视列,也可以指定索引获取列
* @param {Number} columnIndex 索引
*/
getColumns(columnIndex) {
const { visibleColumn } = internalData;
return XEUtils.isUndefined(columnIndex) ? visibleColumn.slice(0) : visibleColumn[columnIndex];
},
/**
* 根据列获取列的唯一主键
*/
getColid(fieldOrColumn) {
const column = handleFieldOrColumn($xeTable, fieldOrColumn);
return column ? column.id : null;
},
/**
* 根据列的唯一主键获取列
* @param {String} colid 列主键
*/
getColumnById(colid) {
const { fullColumnIdData } = internalData;
return colid && fullColumnIdData[colid] ? fullColumnIdData[colid].column : null;
},
/**
* 根据列的字段名获取列
* @param {String} field 字段名
*/
getColumnByField(field) {
const fullColumnFieldData = internalData.fullColumnFieldData;
return field && fullColumnFieldData[field] ? fullColumnFieldData[field].column : null;
},
getParentColumn(fieldOrColumn) {
const { fullColumnIdData } = internalData;
const column = handleFieldOrColumn($xeTable, fieldOrColumn);
return column && column.parentId && fullColumnIdData[column.parentId] ? fullColumnIdData[column.parentId].column : null;
},
/**
* 获取当前表格的列
* 收集到的全量列、全量表头列、处理条件之后的全量表头列、当前渲染中的表头列
*/
getTableColumn() {
return {
collectColumn: internalData.collectColumn.slice(0),
fullColumn: internalData.tableFullColumn.slice(0),
visibleColumn: internalData.visibleColumn.slice(0),
tableColumn: reactData.tableColumn.slice(0)
};
},
/**
* 移动列到指定列的位置
* @param fieldOrColumn
* @param targetFieldOrColumn
* @param options
*/
moveColumnTo(fieldOrColumn, targetFieldOrColumn, options) {
const { fullColumnIdData, visibleColumn } = internalData;
const { dragToChild, dragPos, isCrossDrag } = Object.assign({}, options);
const dragCol = handleFieldOrColumn($xeTable, fieldOrColumn);
let prevDragCol = null;
const colRest = dragCol ? fullColumnIdData[dragCol.id] : null;
let defPos = 'left';
if (XEUtils.isNumber(targetFieldOrColumn)) {
if (colRest && targetFieldOrColumn) {
let currList = colRest.items;
let offsetIndex = colRest._index + targetFieldOrColumn;
if (isCrossDrag) {
currList = visibleColumn;
offsetIndex = colRest._index + targetFieldOrColumn;
}
if (offsetIndex > 0 && offsetIndex < currList.length - 1) {
prevDragCol = currList[offsetIndex];
}
if (targetFieldOrColumn > 0) {
defPos = 'right';
}
}
}
else {
prevDragCol = handleFieldOrColumn($xeTable, targetFieldOrColumn);
const targetColRest = prevDragCol ? fullColumnIdData[prevDragCol.id] : null;
if (colRest && targetColRest) {
if (targetColRest._index > colRest._index) {
defPos = 'right';
}
}
}
return $xeTable.handleColDragSwapEvent(null, true, dragCol, prevDragCol, dragPos || defPos, dragToChild === true);
},
/**
* 移动行到指定行的位置
* @param rowidOrRow
* @param targetRowidOrRow
* @param options
*/
moveRowTo(rowidOrRow, targetRowidOrRow, options) {
const { treeConfig } = props;
const { fullAllDataRowIdData, afterFullData } = internalData;
const { dragToChild, dragPos, isCrossDrag } = Object.assign({}, options);
const treeOpts = computeTreeOpts.value;
const dragRow = handleRowidOrRow($xeTable, rowidOrRow);
let prevDragRow = null;
let defPos = 'top';
const rowRest = dragRow ? fullAllDataRowIdData[getRowid($xeTable, dragRow)] : null;
if (XEUtils.isNumber(targetRowidOrRow)) {
if (rowRest && targetRowidOrRow) {
let currList = afterFullData;
let offsetIndex = rowRest._index + targetRowidOrRow;
if (treeConfig) {
currList = rowRest.items;
if (treeOpts.transform) {
offsetIndex = rowRest.treeIndex + targetRowidOrRow;
if (isCrossDrag) {
currList = afterFullData;
offsetIndex = rowRest._index + targetRowidOrRow;
}
}
}
if (offsetIndex >= 0 && offsetIndex <= currList.length - 1) {
prevDragRow = currList[offsetIndex];
}
if (targetRowidOrRow > 0) {
defPos = 'bottom';
}
}
}
else {
prevDragRow = handleRowidOrRow($xeTable, targetRowidOrRow);
const targetRowRest = prevDragRow ? fullAllDataRowIdData[getRowid($xeTable, prevDragRow)] : null;
if (rowRest && targetRowRest) {
if (targetRowRest._index > rowRest._index) {
defPos = 'bottom';
}
}
}
const rest = $xeTable.handleRowDragSwapEvent(null, true, dragRow, prevDragRow, dragPos || defPos, dragToChild === true);
return rest;
},
/**
* 获取表格的全量列
*/
getFullColumns() {
const { collectColumn } = internalData;
return collectColumn.slice(0);
},
/**
* 获取数据,和 data 的行为一致,也可以指定索引获取数据
*/
getData(rowIndex) {
const tableSynchData = props.data || internalData.tableSynchData;
return XEUtils.isUndefined(rowIndex) ? tableSynchData.slice(0) : tableSynchData[rowIndex];
},
/**
* 用于多选行,获取已选中的数据
*/
getCheckboxRecords(isFull) {
const { treeConfig } = props;
const { updateCheckboxFlag } = reactData;
const { tableFullData, afterFullData, tableFullTreeData, fullDataRowIdData, afterFullRowMaps, selectCheckboxMaps } = internalData;
const treeOpts = computeTreeOpts.value;
const checkboxOpts = computeCheckboxOpts.value;
const { transform, mapChildrenField } = treeOpts;
const { checkField } = checkboxOpts;
const childrenField = treeOpts.children || treeOpts.childrenField;
let rowList = [];
if (updateCheckboxFlag) {
if (checkField) {
if (treeConfig) {
// 如果开启 transform 默认就是完整数据
const currTableData = isFull ? (transform ? tableFullTreeData : tableFullData) : (transform ? tableFullTreeData : afterFullData);
rowList = XEUtils.filterTree(currTableData, row => XEUtils.get(row, checkField), { children: transform ? mapChildrenField : childrenField });
}
else {
const currTableData = isFull ? tableFullData : afterFullData;
rowList = currTableData.filter((row) => XEUtils.get(row, checkField));
}
}
else {
const currMaps = isFull || (treeConfig && !transform) ? fullDataRowIdData : afterFullRowMaps;
XEUtils.each(selectCheckboxMaps, (row, rowid) => {
if (currMaps[rowid]) {
rowList.push(fullDataRowIdData[rowid].row);
}
});
}
}
return rowList;
},
/**
* 只对 tree-config 有效,获取行的子级
*/
getTreeRowChildren(rowOrRowid) {
const { treeConfig } = props;
const { fullAllDataRowIdData } = internalData;
const treeOpts = computeTreeOpts.value;
const { transform, mapChildrenField } = treeOpts;
const childrenField = treeOpts.children || treeOpts.childrenField;
if (rowOrRowid && treeConfig) {
let rowid;
if (XEUtils.isString(rowOrRowid)) {
rowid = rowOrRowid;
}
else {
rowid = getRowid($xeTable, rowOrRowid);
}
if (rowid) {
const rest = fullAllDataRowIdData[rowid];
const row = rest ? rest.row : null;
if (row) {
return row[transform ? mapChildrenField : childrenField] || [];
}
}
}
return [];
},
/**
* 只对 tree-config 有效,用于树形结构,获取指定行的层级
*/
getTreeRowLevel(rowOrRowid) {
const { treeConfig } = props;
const { fullAllDataRowIdData } = internalData;
if (rowOrRowid && treeConfig) {
let rowid;
if (XEUtils.isString(rowOrRowid)) {
rowid = rowOrRowid;
}
else {
rowid = getRowid($xeTable, rowOrRowid);
}
if (rowid) {
const rest = fullAllDataRowIdData[rowid];
if (rest) {
return rest.level;
}
}
}
return -1;
},
/**
* 只对 tree-config 有效,获取行的父级
*/
getTreeParentRow(rowOrRowid) {
const { treeConfig } = props;
const { fullAllDataRowIdData } = internalData;
if (rowOrRowid && treeConfig) {
let rowid;
if (XEUtils.isString(rowOrRowid)) {
rowid = rowOrRowid;
}
else {
rowid = getRowid($xeTable, rowOrRowid);
}
if (rowid) {
const rest = fullAllDataRowIdData[rowid];
if (rest) {
return rest.parent;
}
}
}
return null;
},
getParentRow(rowOrRowid) {
warnLog('vxe.error.delFunc', ['getParentRow', 'getTreeParentRow']);
return $xeTable.getTreeParentRow(rowOrRowid);
},
/**
* 根据行的唯一主键获取行
* @param {String/Number} rowid 行主键
*/
getRowById(cellValue) {
const { fullAllDataRowIdData } = internalData;
const rowid = XEUtils.eqNull(cellValue) ? '' : encodeURIComponent(cellValue || '');
return fullAllDataRowIdData[rowid] ? fullAllDataRowIdData[rowid].row : null;
},
/**
* 根据行获取行的唯一主键
* @param {Row} row 行对象
*/
getRowid(row) {
return getRowid($xeTable, row);
},
/**
* 获取处理后的表格数据
* 如果存在筛选条件,继续处理
* 如果存在排序,继续处理
*/
getTableData() {
const { tableData, footerTableData } = reactData;
const { tableFullData, afterFullData, tableFullTreeData } = internalData;
return {
fullData: props.treeConfig ? tableFullTreeData.slice(0) : tableFullData.slice(0),
visibleData: afterFullData.slice(0),
tableData: tableData.slice(0),
footerData: footerTableData.slice(0)
};
},
/**
* 获取表格的全量数据,如果是 tree-config 则返回带层级的树结构
*/
getFullData() {
const { treeConfig } = props;
const { tableFullData, tableFullTreeData } = internalData;
if (treeConfig) {
return tableFullTreeData.slice(0);
}
return tableFullData.slice(0);
},
/**
* 设置为固定列
*/
setColumnFixed(fieldOrColumn, fixed) {
let status = false;
const cols = XEUtils.isArray(fieldOrColumn) ? fieldOrColumn : [fieldOrColumn];
const columnOpts = computeColumnOpts.value;
const isMaxFixedColumn = computeIsMaxFixedColumn.value;
for (let i = 0; i < cols.length; i++) {
const item = cols[i];
const column = handleFieldOrColumn($xeTable, item);
const targetColumn = getRootColumn($xeTable, column);
if (targetColumn && targetColumn.fixed !== fixed) {
// 是否超过最大固定列数量
if (!targetColumn.fixed && isMaxFixedColumn) {
if (VxeUI.modal) {
VxeUI.modal.message({
status: 'error',
content: getI18n('vxe.table.maxFixedCol', [columnOpts.maxFixedSize])
});
}
return nextTick();
}
XEUtils.eachTree([targetColumn], (column) => {
column.fixed = fixed;
column.renderFixed = fixed;
});
$xeTable.saveCustomStore('update:fixed');
if (!status) {
status = true;
}
}
}
if (status) {
return $xeTable.refreshColumn();
}
return nextTick();
},
/**
* 取消指定固定列
*/
clearColumnFixed(fieldOrColumn) {
let status = false;
const cols = XEUtils.isArray(fieldOrColumn) ? fieldOrColumn : [fieldOrColumn];
cols.forEach(item => {
const column = handleFieldOrColumn($xeTable, item);
const targetColumn = getRootColumn($xeTable, column);
if (targetColumn && targetColumn.fixed) {
XEUtils.eachTree([targetColumn], (column) => {
column.fixed = null;
column.renderFixed = null;
});
$xeTable.saveCustomStore('update:fixed');
if (!status) {
status = true;
}
}
});
if (status) {
return $xeTable.refreshColumn();
}
return nextTick();
},
/**
* 隐藏指定列
*/
hideColumn: handleColumnVisible(false),
/**
* 显示指定列
*/
showColumn: handleColumnVisible(true),
setColumnWidth(fieldOrColumn, width) {
const { elemStore } = internalData;
let status = false;
const cols = XEUtils.isArray(fieldOrColumn) ? fieldOrColumn : [fieldOrColumn];
let cWidth = XEUtils.toInteger(width);
if (isScale(width)) {
const bodyScrollElem = getRefElem(elemStore['main-body-scroll']);
const bodyWidth = bodyScrollElem ? bodyScrollElem.clientWidth - 1 : 0;
cWidth = Math.floor(cWidth * bodyWidth);
}
if (cWidth) {
cols.forEach(item => {
const column = handleFieldOrColumn($xeTable, item);
if (column) {
column.resizeWidth = cWidth;
if (!status) {
status = true;
}
}
});
if (status) {
return $xeTable.refreshColumn().then(() => {
return { status };
});
}
}
return nextTick().then(() => {
return { status };
});
},
getColumnWidth(fieldOrColumn) {
const column = handleFieldOrColumn($xeTable, fieldOrColumn);
if (column) {
return column.renderWidth;
}
return 0;
},
/**
* 手动重置列的显示隐藏、列宽拖动的状态、固定列、排序列;
* 如果为 true 则重置所有状态
* 如果已关联工具栏,则会同步更新
*/
resetColumn(options) {
warnLog('vxe.error.delFunc', ['resetColumn', 'resetCustom']);
return $xeTable.resetCustom(options);
},
/**
* 刷新列信息
* 将固定的列左边、右边分别靠边
* 如果传 true 则会检查列顺序并排序
*/
refreshColumn(initSort) {
if (initSort) {
handleUpdateColumn();
}
return parseColumns(true).then(() => {
return $xeTable.refreshScroll();
}).then(() => {
return handleLazyRecalculate(false, true, true);
});
},
setRowHeightConf(heightConf) {
const { fullAllDataRowIdData } = internalData;
let status = false;
if (heightConf) {
XEUtils.each(heightConf, (height, rowid) => {
const rowRest = fullAllDataRowIdData[rowid];
if (rowRest) {
const rHeight = XEUtils.toInteger(height);
if (rHeight) {
rowRest.resizeHeight = rHeight;
if (!status) {
status = true;
}
}
}
});
if (status) {
internalData.isResizeCellHeight = true;
reactData.resizeHeightFlag++;
}
}
return nextTick().then(() => {
updateRowOffsetTop();
return { status };
});
},
getRowHeightConf(isFull) {
const { fullAllDataRowIdData, afterFullData } = internalData;
const { handleGetRowId } = createHandleGetRowId($xeTable);
const rowOpts = computeRowOpts.value;
const cellOpts = computeCellOpts.value;
const defaultRowHeight = computeDefaultRowHeight.value;
const rest = {};
afterFullData.forEach(row => {
const rowid = handleGetRowId(row);
const rowRest = fullAllDataRowIdData[rowid];
if (rowRest) {
const resizeHeight = rowRest.resizeHeight;
if (resizeHeight || isFull) {
const currCellHeight = getCellRestHeight(rowRest, cellOpts, rowOpts, defaultRowHeight);
rest[rowid] = currCellHeight;
}
}
});
return rest;
},
recalcRowHeight(rowOrId) {
const { fullAllDataRowIdData } = internalData;
const rows = XEUtils.isArray(rowOrId) ? rowOrId : [rowOrId];
const el = refElem.value;
if (el) {
const { handleGetRowId } = createHandleGetRowId($xeTable);
el.setAttribute('data-calc-row', 'Y');
rows.forEach(row => {
const rowid = XEUtils.isString(row) || XEUtils.isNumber(row) ? row : handleGetRowId(row);
const rowRest = fullAllDataRowIdData[rowid];
if (rowRest) {
rowRest.resizeHeight = calcCellAutoHeight(rowid, rowRest, el);
}
el.removeAttribute('data-calc-row');
});
reactData.calcCellHeightFlag++;
}
return nextTick();
},
setRowHeight(rowOrId, height) {
const { fullAllDataRowIdData } = internalData;
let status = false;
const rows = XEUtils.isArray(rowOrId) ? rowOrId : [rowOrId];
let rHeight = XEUtils.toInteger(height);
if (isScale(height)) {
const tableBody = refTableBody.value;
const bodyElem = tableBody ? tableBody.$el : null;
const bodyHeight = bodyElem ? bodyElem.clientHeight - 1 : 0;
rHeight = Math.floor(rHeight * bodyHeight);
}
if (rHeight) {
const { handleGetRowId } = createHandleGetRowId($xeTable);
rows.forEach(row => {
const rowid = XEUtils.isString(row) || XEUtils.isNumber(row) ? row : handleGetRowId(row);
const rowRest = fullAllDataRowIdData[rowid];
if (rowRest) {
rowRest.resizeHeight = rHeight;
if (!status) {
status = true;
}
}
});
if (status) {
internalData.isResizeCellHeight = true;
reactData.resizeHeightFlag++;
}
}
return nextTick().then(() => {
return { status };
});
},
getRowHeight(rowOrId) {
const { fullAllDataRowIdData } = internalData;
const rowOpts = computeRowOpts.value;
const cellOpts = computeCellOpts.value;
const defaultRowHeight = computeDefaultRowHeight.value;
const rowid = XEUtils.isString(rowOrId) || XEUtils.isNumber(rowOrId) ? rowOrId : getRowid($xeTable, rowOrId);
const rowRest = fullAllDataRowIdData[rowid];
if (rowRest) {
return getCellRestHeight(rowRest, cellOpts, rowOpts, defaultRowHeight);
}
return 0;
},
/**
* 刷新滚动操作,手动同步滚动相关位置(对于某些特殊的操作,比如滚动条错位、固定列不同步)
*/
refreshScroll() {
const { elemStore, lastScrollLeft, lastScrollTop } = internalData;
const headerScrollElem = getRefElem(elemStore['main-header-scroll']);
const bodyScrollElem = getRefElem(elemStore['main-body-scroll']);
const footerScrollElem = getRefElem(elemStore['main-footer-scroll']);
const leftScrollElem = getRefElem(elemStore['left-body-scroll']);
const rightScrollElem = getRefElem(elemStore['right-body-scroll']);
const xHandleEl = refScrollXHandleElem.value;
const yHandleEl = refScrollYHandleElem.value;
return new Promise(resolve => {
// 还原滚动条位置
if (lastScrollLeft || lastScrollTop) {
return restoreScrollLocation($xeTable, lastScrollLeft, lastScrollTop).then(() => {
// 存在滚动行为未结束情况
setTimeout(resolve, 10);
});
}
internalData.intoRunScroll = true;
// 重置
setScrollTop(yHandleEl, lastScrollTop);
setScrollTop(bodyScrollElem, lastScrollTop);
setScrollTop(leftScrollElem, lastScrollTop);
setScrollTop(rightScrollElem, lastScrollTop);
setScrollLeft(xHandleEl, lastScrollLeft);
setScrollLeft(bodyScrollElem, lastScrollLeft);
setScrollLeft(headerScrollElem, lastScrollLeft);
setScrollLeft(footerScrollElem, lastScrollLeft);
// 存在滚动行为未结束情况
setTimeout(() => {
internalData.intoRunScroll = false;
resolve();
}, 10);
});
},
/**
* 重新渲染布局
* 刷新布局
*/
recalculate(reFull) {
const isForce = !!reFull;
return handleLazyRecalculate(isForce, isForce, isForce);
},
openTooltip(target, content) {
const $commTip = refCommTooltip.value;
if ($commTip && $commTip.open) {
return $commTip.open(target, content);
}
return nextTick();
},
/**
* 关闭 tooltip
*/
closeTooltip() {
const { tooltipStore } = reactData;
const $tooltip = refTooltip.value;
const $commTip = refCommTooltip.value;
if (tooltipStore.visible) {
Object.assign(tooltipStore, {
row: null,
column: null,
content: null,
visible: false,
type: null,
currOpts: {}
});
if ($tooltip && $tooltip.close) {
$tooltip.close();
}
}
if ($commTip && $commTip.close) {
$commTip.close();
}
return nextTick();
},
/**
* 判断列头复选框是否被选中
*/
isAllCheckboxChecked() {
return reactData.isAllSelected;
},
/**
* 判断列头复选框是否被半选
*/
isAllCheckboxIndeterminate() {
return !reactData.isAllSelected && reactData.isIndeterminate;
},
/**
* 获取复选框半选状态的行数据
*/
getCheckboxIndeterminateRecords(isFull) {
const { treeConfig } = props;
const { fullDataRowIdData, treeIndeterminateRowMaps } = internalData;
if (treeConfig) {
const fullRest = [];
const defRest = [];
XEUtils.each(treeIndeterminateRowMaps, (item, rowid) => {
if (item) {
fullRest.push(item);
if (fullDataRowIdData[rowid]) {
defRest.push(item);
}
}
});
if (isFull) {
return fullRest;
}
return defRest;
}
return [];
},
/**
* 用于多选行,设置行为选中状态,第二个参数为选中与否
* @param {Array/Row} rows 行数据
* @param {Boolean} value 是否选中
*/
setCheckboxRow(rows, checked) {
if (rows && !XEUtils.isArray(rows)) {
rows = [rows];
}
return handleCheckedCheckboxRow(rows, checked, true);
},
setCheckboxRowByKey(keys, checked) {
const { fullAllDataRowIdData } = internalData;
if (!XEUtils.isArray(keys)) {
keys = [keys];
}
const rows = [];
keys.forEach((rowKey) => {
const rowid = encodeRowid(rowKey);
const rowRest = fullAllDataRowIdData[rowid];
if (rowRest) {
rows.push(rowRest.row);
}
});
return handleCheckedCheckboxRow(rows, checked, true);
},
setCheckboxRowKey(keys, checked) {
return $xeTable.setCheckboxRowByKey(keys, checked);
},
isCheckedByCheckboxRow(row) {
const { updateCheckboxFlag } = reactData;
const { selectCheckboxMaps } = internalData;
const checkboxOpts = computeCheckboxOpts.value;
const { checkField } = checkboxOpts;
if (checkField) {
return XEUtils.get(row, checkField);
}
return !!updateCheckboxFlag && !!selectCheckboxMaps[getRowid($xeTable, row)];
},
isCheckedByCheckboxRowKey(rowKey) {
const { updateCheckboxFlag } = reactData;
const { fullAllDataRowIdData, selectCheckboxMaps } = internalData;
const checkboxOpts = computeCheckboxOpts.value;
const { checkField } = checkboxOpts;
const rowid = encodeRowid(rowKey);
if (checkField) {
const rowRest = fullAllDataRowIdData[rowid];
if (rowRest) {
return XEUtils.get(rowRest.row, checkField);
}
return false;
}
return !!updateCheckboxFlag && !!selectCheckboxMaps[rowid];
},
isIndeterminateByCheckboxRow(row) {
const { treeIndeterminateRowMaps } = internalData;
return !!treeIndeterminateRowMaps[getRowid($xeTable, row)] && !$xeTable.isCheckedByCheckboxRow(row);
},
isIndeterminateByCheckboxRowKey(rowKey) {
const { treeIndeterminateRowMaps } = internalData;
const rowid = encodeRowid(rowKey);
return !!treeIndeterminateRowMaps[rowid] && !$xeTable.isCheckedByCheckboxRowKey(rowid);
},
/**
* 多选,切换某一行的选中状态
*/
toggleCheckboxRow(row) {
const { selectCheckboxMaps } = internalData;
const checkboxOpts = computeCheckboxOpts.value;
const { checkField } = checkboxOpts;
const checked = checkField ? !XEUtils.get(row, checkField) : !selectCheckboxMaps[getRowid($xeTable, row)];
$xeTable.handleBatchSelectRows([row], checked, true);
$xeTable.checkSelectionStatus();
return nextTick();
},
/**
* 用于多选行,设置所有行的选中状态
* @param {Boolean} value 是否选中
*/
setAllCheckboxRow(value) {
return handleCheckedAllCheckboxRow(value, true);
},
/**
* 获取单选框保留选中的行
*/
getRadioReserveRecord(isFull) {
const { treeConfig } = props;
const { fullDataRowIdData, radioReserveRow, afterFullData } = internalData;
const radioOpts = computeRadioOpts.value;
const treeOpts = computeTreeOpts.value;
const childrenField = treeOpts.children || treeOpts.childrenField;
if (radioOpts.reserve && radioReserveRow) {
const rowid = getRowid($xeTable, radioReserveRow);
if (isFull) {
if (!fullDataRowIdData[rowid]) {
return radioReserveRow;
}
}
else {
const rowkey = getRowkey($xeTable);
if (treeConfig) {
const matchObj = XEUtils.findTree(afterFullData, row => rowid === XEUtils.get(row, rowkey), { children: childrenField });
if (matchObj) {
return radioReserveRow;
}
}
else {
if (!afterFullData.some(row => rowid === XEUtils.get(row, rowkey))) {
return radioReserveRow;
}
}
}
}
return null;
},
clearRadioReserve() {
internalData.radioReserveRow = null;
return nextTick();
},
/**
* 获取复选框保留选中的行
*/
getCheckboxReserveRecords(isFull) {
const { treeConfig } = props;
const { afterFullData, fullDataRowIdData, checkboxReserveRowMap } = internalData;
const checkboxOpts = computeCheckboxOpts.value;
const treeOpts = computeTreeOpts.value;
const childrenField = treeOpts.children || treeOpts.childrenField;
const reserveSelection = [];
if (checkboxOpts.reserve) {
const { handleGetRowId } = createHandleGetRowId($xeTable);
const afterFullIdMaps = {};
if (treeConfig) {
XEUtils.eachTree(afterFullData, row => {
afterFullIdMaps[handleGetRowId(row)] = 1;
}, { children: childrenField });
}
else {
afterFullData.forEach(row => {
afterFullIdMaps[handleGetRowId(row)] = 1;
});
}
XEUtils.each(checkboxReserveRowMap, (oldRow, oldRowid) => {
if (oldRow) {
if (isFull) {
if (!fullDataRowIdData[oldRowid]) {
reserveSelection.push(oldRow);
}
}
else {
if (!afterFullIdMaps[oldRowid]) {
reserveSelection.push(oldRow);
}
}
}
});
}
return reserveSelection;
},
clearCheckboxReserve() {
internalData.checkboxReserveRowMap = {};
return nextTick();
},
/**
* 多选,切换所有行的选中状态
*/
toggleAllCheckboxRow() {
handleCheckAllEvent(null, !reactData.isAllSelected);
return nextTick();
},
/**
* 用于多选行,手动清空用户的选择
* 清空行为不管是否被禁用还是保留记录,都将彻底清空选中状态
*/
clearCheckboxRow() {
const { treeConfig } = props;
const { tableFullData } = internalData;
const treeOpts = computeTreeOpts.value;
const childrenField = treeOpts.children || treeOpts.childrenField;
const checkboxOpts = computeCheckboxOpts.value;
const { checkField, reserve } = checkboxOpts;
// indeterminateField 仅支持读取
const indeterminateField = checkboxOpts.indeterminateField || checkboxOpts.halfField;
if (checkField) {
const handleClearChecked = (item) => {
if (treeConfig && indeterminateField) {
XEUtils.set(item, indeterminateField, false);
}
XEUtils.set(item, checkField, false);
};
if (treeConfig) {
XEUtils.eachTree(tableFullData, handleClearChecked, { children: childrenField });
}
else {
tableFullData.forEach(handleClearChecked);
}
}
if (reserve) {
tableFullData.forEach((row) => handleCheckboxReserveRow(row, false));
}
reactData.isAllSelected = false;
reactData.isIndeterminate = false;
internalData.selectCheckboxMaps = {};
internalData.treeIndeterminateRowMaps = {};
reactData.updateCheckboxFlag++;
return nextTick();
},
/**
* 用于当前行,设置某一行为高亮状态
* @param {Row} row 行对象
*/
setCurrentRow(row) {
const $xeGanttView = internalData.xeGanttView;
const rowOpts = computeRowOpts.value;
const el = refElem.value;
$xeTable.clearCurrentRow();
// $xeTable.clearCurrentColumn()
internalData.currentRow = row;
if (rowOpts.isCurrent || props.highlightCurrentRow) {
if (el) {
XEUtils.arrayEach(el.querySelectorAll(`[rowid="${getRowid($xeTable, row)}"]`), elem => addClass(elem, 'row--current'));
}
}
if ($xeGanttView && $xeGanttView.handleUpdateCurrentRow) {
$xeGanttView.handleUpdateCurrentRow(row);
}
return nextTick();
},
isCheckedByRadioRow(row) {
const { selectRadioRow } = reactData;
if (row && selectRadioRow) {
return $xeTable.eqRow(selectRadioRow, row);
}
return false;
},
isCheckedByRadioRowKey(key) {
const { selectRadioRow } = reactData;
if (selectRadioRow) {
return key === getRowid($xeTable, selectRadioRow);
}
return false;
},
/**
* 用于单选行,设置某一行为选中状态
* @param {Row} row 行对象
*/
setRadioRow(row) {
return handleCheckedRadioRow(row, true);
},
/**
* 用于单选行,设置某一行为选中状态
* @param key 行主键
*/
setRadioByRowKey(rowKey) {
const { fullAllDataRowIdData } = internalData;
const rowid = encodeRowid(rowKey);
const rowRest = fullAllDataRowIdData[rowid];
if (rowRest) {
return handleCheckedRadioRow(rowRest.row, true);
}
return nextTick();
},
setRadioRowKey(rowKey) {
return $xeTable.setRadioByRowKey(rowKey);
},
/**
* 用于当前行,手动清空当前高亮的状态
*/
clearCurrentRow() {
const $xeGanttView = internalData.xeGanttView;
const el = refElem.value;
internalData.currentRow = null;
internalData.hoverRow = null;
if (el) {
XEUtils.arrayEach(el.querySelectorAll('.row--current'), elem => removeClass(elem, 'row--current'));
}
if ($xeGanttView && $xeGanttView.handleUpdateCurrentRow) {
$xeGanttView.handleUpdateCurrentRow();
}
return nextTick();
},
/**
* 用于单选行,手动清空用户的选择
*/
clearRadioRow() {
reactData.selectRadioRow = null;
return nextTick();
},
/**
* 用于当前行,获取当前行的数据
*/
getCurrentRecord(isFull) {
const { fullDataRowIdData, afterFullRowMaps, currentRow } = internalData;
const rowOpts = computeRowOpts.value;
if (rowOpts.isCurrent || props.highlightCurrentRow) {
const rowid = getRowid($xeTable, currentRow);
if (isFull) {
if (fullDataRowIdData[rowid]) {
return currentRow;
}
}
else {
if (afterFullRowMaps[rowid]) {
return currentRow;
}
}
}
return null;
},
/**
* 用于单选行,获取当已选中的数据
*/
getRadioRecord(isFull) {
const { fullDataRowIdData, afterFullRowMaps } = internalData;
const { selectRadioRow } = reactData;
if (selectRadioRow) {
const rowid = getRowid($xeTable, selectRadioRow);
if (isFull) {
if (fullDataRowIdData[rowid]) {
return selectRadioRow;
}
}
else {
if (afterFullRowMaps[rowid]) {
return selectRadioRow;
}
}
}
return null;
},
getCurrentColumn() {
const columnOpts = computeColumnOpts.value;
return columnOpts.isCurrent || props.highlightCurrentColumn ? reactData.currentColumn : null;
},
/**
* 用于当前列,设置某列行为高亮状态
*/
setCurrentColumn(fieldOrColumn) {
const { mouseConfig } = props;
const mouseOpts = computeMouseOpts.value;
const isMouseSelected = mouseConfig && mouseOpts.selected;
const column = handleFieldOrColumn($xeTable, fieldOrColumn);
if (column) {
$xeTable.clearCurrentColumn();
reactData.currentColumn = column;
}
return nextTick().then(() => {
// 更新状选中态
if (isMouseSelected) {
$xeTable.addCellSelectedClass();
}
});
},
/**
* 用于当前列,手动清空当前高亮的状态
*/
clearCurrentColumn() {
reactData.currentColumn = null;
return nextTick();
},
setPendingRow(rows, status) {
const { handleGetRowId } = createHandleGetRowId($xeTable);
const { pendingRowMaps } = internalData;
if (rows && !XEUtils.isArray(rows)) {
rows = [rows];
}
if (status) {
rows.forEach((row) => {
const rowid = handleGetRowId(row);
if (rowid && !pendingRowMaps[rowid]) {
pendingRowMaps[rowid] = row;
}
});
}
else {
rows.forEach((row) => {
const rowid = handleGetRowId(row);
if (rowid && pendingRowMaps[rowid]) {
delete pendingRowMaps[rowid];
}
});
}
reactData.pendingRowFlag++;
return nextTick();
},
togglePendingRow(rows) {
const { handleGetRowId } = createHandleGetRowId($xeTable);
const { pendingRowMaps } = internalData;
if (rows && !XEUtils.isArray(rows)) {
rows = [rows];
}
rows.forEach((row) => {
const rowid = handleGetRowId(row);
if (rowid) {
if (pendingRowMaps[rowid]) {
delete pendingRowMaps[rowid];
}
else {
pendingRowMaps[rowid] = row;
}
}
});
reactData.pendingRowFlag++;
return nextTick();
},
hasPendingByRow(row) {
return $xeTable.isPendingByRow(row);
},
isPendingByRow(row) {
const { pendingRowMaps } = internalData;
const rowid = getRowid($xeTable, row);
return !!pendingRowMaps[rowid];
},
getPendingRecords() {
const { fullAllDataRowIdData, pendingRowMaps } = internalData;
const insertRecords = [];
XEUtils.each(pendingRowMaps, (row, rowid) => {
if (fullAllDataRowIdData[rowid]) {
insertRecords.push(row);
}
});
return insertRecords;
},
clearPendingRow() {
internalData.pendingRowMaps = {};
reactData.pendingRowFlag++;
return nextTick();
},
sort(sortConfs, sortOrder) {
const sortOpts = computeSortOpts.value;
const { multiple, remote, orders } = sortOpts;
if (sortConfs) {
if (XEUtils.isString(sortConfs)) {
sortConfs = [
{ field: sortConfs, order: sortOrder }
];
}
}
if (!XEUtils.isArray(sortConfs)) {
sortConfs = [sortConfs];
}
if (sortConfs.length) {
if (!multiple) {
clearAllSort();
}
(multiple ? sortConfs : [sortConfs[0]]).forEach((confs, index) => {
let { field, order } = confs;
let column = field;
if (XEUtils.isString(field)) {
column = $xeTable.getColumnByField(field);
}
if (column && column.sortable) {
if (orders && orders.indexOf(order) === -1) {
order = getNextSortOrder(column);
}
if (column.order !== order) {
column.order = order;
}
column.sortTime = Date.now() + index;
}
});
// 如果是服务端排序,则跳过本地排序处理
if (!remote) {
$xeTable.handleTableData(true);
}
return nextTick().then(() => {
updateRowOffsetTop();
$xeTable.updateCellAreas();
return updateStyle();
});
}
return nextTick();
},
setSort(sortConfs, isUpdate) {
return handleSortEvent(null, sortConfs, isUpdate);
},
setSortByEvent(evnt, sortConfs) {
return handleSortEvent(evnt, sortConfs, true);
},
/**
* 清空指定列的排序条件
* 如果为空则清空所有列的排序条件
* @param {String} fieldOrColumn 列或字段名
*/
clearSort(fieldOrColumn) {
const sortOpts = computeSortOpts.value;
if (fieldOrColumn) {
const column = handleFieldOrColumn($xeTable, fieldOrColumn);
if (column) {
column.order = null;
}
}
else {
clearAllSort();
}
if (!sortOpts.remote) {
$xeTable.handleTableData(true);
}
return nextTick().then(() => {
updateRowOffsetTop();
return updateStyle();
});
},
clearSortByEvent(evnt, fieldOrColumn) {
const { tableFullColumn } = internalData;
const sortOpts = computeSortOpts.value;
const { multiple } = sortOpts;
const sortCols = [];
let column = null;
if (evnt) {
if (fieldOrColumn) {
column = handleFieldOrColumn($xeTable, fieldOrColumn);
if (column) {
column.order = null;
}
}
else {
tableFullColumn.forEach((column) => {
if (column.order) {
column.order = null;
sortCols.push(column);
}
});
}
if (!sortOpts.remote) {
$xeTable.handleTableData(true);
}
if (!multiple) {
column = sortCols[0];
}
if (column) {
$xeTable.handleColumnSortEvent(evnt, column);
}
if (multiple && sortCols.length) {
const params = { $table: $xeTable, $event: evnt, cols: sortCols, sortList: [] };
dispatchEvent('clear-all-sort', params, evnt);
}
}
return nextTick().then(() => {
updateRowOffsetTop();
return updateStyle();
});
},
isSort(fieldOrColumn) {
if (fieldOrColumn) {
const column = handleFieldOrColumn($xeTable, fieldOrColumn);
return column ? column.sortable && !!column.order : false;
}
return $xeTable.getSortColumns().length > 0;
},
getSortColumns() {
const sortOpts = computeSortOpts.value;
const { multiple, chronological } = sortOpts;
const sortList = [];
const { tableFullColumn } = internalData;
tableFullColumn.forEach((column) => {
const { field, order } = column;
if (column.sortable && order) {
sortList.push({ column, field, property: field, order: order, sortTime: column.sortTime });
}
});
if (multiple && chronological && sortList.length > 1) {
return XEUtils.orderBy(sortList, 'sortTime');
}
return sortList;
},
setFilterByEvent(evnt, fieldOrColumn, options) {
const column = handleFieldOrColumn($xeTable, fieldOrColumn);
if (column && column.filters) {
column.filters = toFilters(options || [], column.id);
return $xeTable.handleColumnConfirmFilter(column, evnt);
}
return nextTick();
},
/**
* 关闭筛选
* @param {Event} evnt 事件
*/
closeFilter() {
const { filterStore } = reactData;
const { column, visible } = filterStore;
filterStore.isAllSelected = false;
filterStore.isIndeterminate = false;
filterStore.visible = false;
if (visible) {
const field = column ? column.field : null;
dispatchEvent('filter-visible', {
column,
property: field,
field,
filterList: () => $xeTable.getCheckedFilters(),
visible: false
}, null);
}
return nextTick();
},
/**
* 判断指定列是否为筛选状态,如果为空则判断所有列
* @param {String} fieldOrColumn 字段名
*/
isActiveFilterByColumn(fieldOrColumn) {
const column = handleFieldOrColumn($xeTable, fieldOrColumn);
if (column) {
return column.filters && column.filters.some((option) => option.checked);
}
return $xeTable.getCheckedFilters().length > 0;
},
isFilter(fieldOrColumn) {
return $xeTable.isActiveFilterByColumn(fieldOrColumn);
},
clearFilterByEvent(evnt, fieldOrColumn) {
const { filterStore } = reactData;
const { tableFullColumn } = internalData;
const filterOpts = computeFilterOpts.value;
const { multiple } = filterOpts;
const filterCols = [];
let column = null;
if (fieldOrColumn) {
column = handleFieldOrColumn($xeTable, fieldOrColumn);
if (column) {
$xeTable.handleClearFilter(column);
}
}
else {
tableFullColumn.forEach(column => {
if (column.filters) {
filterCols.push(column);
$xeTable.handleClearFilter(column);
}
});
}
if (!fieldOrColumn || column !== filterStore.column) {
Object.assign(filterStore, {
isAllSelected: false,
isIndeterminate: false,
style: null,
options: [],
column: null,
multiple: false, // 选项是覅多选
visible: false
});
}
if (!filterOpts.remote) {
$xeTable.updateData();
}
if (!multiple) {
column = filterCols[0];
}
if (column) {
const filterList = () => $xeTable.getCheckedFilters();
const values = [];
const datas = [];
column.filters.forEach((item) => {
if (item.checked) {
values.push(item.value);
datas.push(item.data);
}
});
const params = {
$table: $xeTable,
$event: evnt,
column,
field: column.field,
property: column.field,
values,
datas,
filters: filterList,
filterList
};
$xeTable.dispatchEvent('filter-change', params, evnt);
$xeTable.dispatchEvent('clear-filter', params, evnt);
}
if (multiple && filterCols.length) {
const params = { $table: $xeTable, $event: evnt, cols: filterCols, filterList: [] };
dispatchEvent('clear-all-filter', params, evnt);
}
return nextTick();
},
/**
* 判断展开行是否懒加载完成
* @param {Row} row 行对象
*/
isRowExpandLoaded(row) {
const { fullAllDataRowIdData } = internalData;
const rowRest = fullAllDataRowIdData[getRowid($xeTable, row)];
return rowRest && !!rowRest.expandLoaded;
},
clearRowExpandLoaded(row) {
const { fullAllDataRowIdData, rowExpandLazyLoadedMaps } = internalData;
const expandOpts = computeExpandOpts.value;
const { lazy } = expandOpts;
const rowid = getRowid($xeTable, row);
const rowRest = fullAllDataRowIdData[rowid];
if (lazy && rowRest) {
rowRest.expandLoaded = false;
delete rowExpandLazyLoadedMaps[rowid];
}
reactData.rowExpandedFlag++;
return nextTick();
},
/**
* 重新懒加载展开行,并展开内容
* @param {Row} row 行对象
*/
reloadRowExpand(row) {
const { rowExpandLazyLoadedMaps } = internalData;
const expandOpts = computeExpandOpts.value;
const { lazy } = expandOpts;
const rowid = getRowid($xeTable, row);
if (lazy && !rowExpandLazyLoadedMaps[rowid]) {
$xeTable.clearRowExpandLoaded(row)
.then(() => handleAsyncRowExpand(row));
}
return nextTick();
},
reloadExpandContent(row) {
warnLog('vxe.error.delFunc', ['reloadExpandContent', 'reloadRowExpand']);
// 即将废弃
return $xeTable.reloadRowExpand(row);
},
/**
* 切换展开行
*/
toggleRowExpand(row) {
return $xeTable.setRowExpand(row, !$xeTable.isRowExpandByRow(row));
},
/**
* 设置所有行的展开与否
* @param {Boolean} expanded 是否展开
*/
setAllRowExpand(expanded) {
const treeOpts = computeTreeOpts.value;
const { tableFullData, tableFullTreeData } = internalData;
const childrenField = treeOpts.children || treeOpts.childrenField;
let expandedRows = [];
if (props.treeConfig) {
XEUtils.eachTree(tableFullTreeData, (row) => {
expandedRows.push(row);
}, { children: childrenField });
}
else {
expandedRows = tableFullData;
}
return $xeTable.setRowExpand(expandedRows, expanded);
},
/**
* 设置展开行,二个参数设置这一行展开与否
* 支持单行
* 支持多行
* @param {Array/Row} rows 行数据
* @param {Boolean} expanded 是否展开
*/
setRowExpand(rows, expanded) {
const { expandColumn } = reactData;
let { fullAllDataRowIdData, rowExpandedMaps, rowExpandLazyLoadedMaps } = internalData;
const { handleGetRowId } = createHandleGetRowId($xeTable);
const expandOpts = computeExpandOpts.value;
const { reserve, lazy, accordion, toggleMethod } = expandOpts;
const lazyRests = [];
const columnIndex = expandColumn ? $xeTable.getColumnIndex(expandColumn) : -1;
const $columnIndex = expandColumn ? $xeTable.getVMColumnIndex(expandColumn) : -1;
if (rows) {
if (!XEUtils.isArray(rows)) {
rows = [rows];
}
if (accordion) {
// 只能同时展开一个
rowExpandedMaps = {};
internalData.rowExpandedMaps = rowExpandedMaps;
rows = rows.slice(rows.length - 1, rows.length);
}
const validRows = toggleMethod ? rows.filter((row) => toggleMethod({ $table: $xeTable, expanded, column: expandColumn, columnIndex, $columnIndex, row, rowIndex: $xeTable.getRowIndex(row), $rowIndex: $xeTable.getVMRowIndex(row) })) : rows;
if (expanded) {
validRows.forEach((row) => {
const rowid = handleGetRowId(row);
if (!rowExpandedMaps[rowid]) {
const rowRest = fullAllDataRowIdData[rowid];
const isLoad = lazy && !rowRest.expandLoaded && !rowExpandLazyLoadedMaps[rowid];
if (isLoad) {
lazyRests.push(handleAsyncRowExpand(row));
}
else {
rowExpandedMaps[rowid] = row;
}
}
});
}
else {
validRows.forEach(item => {
const rowid = handleGetRowId(item);
if (rowExpandedMaps[rowid]) {
delete rowExpandedMaps[rowid];
}
});
}
if (reserve) {
validRows.forEach((row) => handleRowExpandReserve(row, expanded));
}
}
reactData.rowExpandedFlag++;
return Promise.all(lazyRests)
.then(() => nextTick())
.then(() => handleLazyRecalculate(true, true, true))
.then(() => {
updateRowOffsetTop();
updateRowExpandStyle();
handleRowExpandScroll();
return $xeTable.updateCellAreas();
});
},
/**
* 判断行是否为展开状态
* @param {Row} row 行对象
*/
isRowExpandByRow(row) {
const { rowExpandedFlag } = reactData;
const { rowExpandedMaps } = internalData;
const rowid = getRowid($xeTable, row);
return !!rowExpandedFlag && !!rowExpandedMaps[rowid];
},
isExpandByRow(row) {
// 已废弃
warnLog('vxe.error.delFunc', ['isExpandByRow', 'isRowExpandByRow']);
return $xeTable.isRowExpandByRow(row);
},
/**
* 手动清空展开行状态,数据会恢复成未展开的状态
*/
clearRowExpand() {
const { tableFullData, scrollYStore } = internalData;
const expandOpts = computeExpandOpts.value;
const { reserve } = expandOpts;
const expList = $xeTable.getRowExpandRecords();
internalData.rowExpandedMaps = {};
if (reserve) {
tableFullData.forEach((row) => handleRowExpandReserve(row, false));
}
reactData.rowExpandedFlag++;
scrollYStore.startIndex = 0;
scrollYStore.endIndex = 1;
return nextTick().then(() => {
if (expList.length) {
return handleLazyRecalculate(true, true, true);
}
}).then(() => {
updateRowOffsetTop();
updateRowExpandStyle();
handleRowExpandScroll();
return $xeTable.updateCellAreas();
});
},
clearRowExpandReserve() {
internalData.rowExpandedReserveRowMap = {};
return nextTick();
},
getRowExpandRecords() {
const rest = [];
XEUtils.each(internalData.rowExpandedMaps, item => {
if (item) {
rest.push(item);
}
});
return rest;
},
setRowGroups(fieldOrColumns) {
const { aggregateConfig, rowGroupConfig } = props;
const aggregateOpts = computeAggregateOpts.value;
const { maxGroupSize } = aggregateOpts;
if (!(aggregateConfig || rowGroupConfig)) {
errLog('vxe.error.reqProp', ['aggregate-config']);
return nextTick();
}
const confList = fieldOrColumns ? (XEUtils.isArray(fieldOrColumns) ? fieldOrColumns : [fieldOrColumns]) : [];
if (maxGroupSize && confList.length > maxGroupSize) {
if (VxeUI.modal) {
VxeUI.modal.message({
status: 'error',
content: getI18n('vxe.table.maxGroupCol', [maxGroupSize])
});
}
return nextTick();
}
if (confList.length) {
handleUpdateRowGroup(confList.map(fieldOrColumn => {
return XEUtils.isString(fieldOrColumn) ? fieldOrColumn : fieldOrColumn.field;
}));
return loadTableData(internalData.tableSynchData, false, true);
}
return nextTick();
},
getRowGroups() {
const { aggregateConfig, rowGroupConfig } = props;
const { fullColumnFieldData } = internalData;
if (aggregateConfig || rowGroupConfig) {
const { rowGroupList } = reactData;
return rowGroupList.map(({ field }) => {
const colRet = fullColumnFieldData[field];
if (colRet) {
return colRet.column;
}
return { field };
});
}
return [];
},
getRowGroupFields() {
return $xeTable.getRowGroups().map(item => item.field);
},
clearRowGroups() {
const { aggregateConfig, rowGroupConfig } = props;
if (!(aggregateConfig || rowGroupConfig)) {
errLog('vxe.error.reqProp', ['aggregate-config']);
return nextTick();
}
handleUpdateRowGroup([]);
return loadTableData(internalData.tableSynchData, false, true);
},
isRowGroupRecord(row) {
warnLog('vxe.error.delFunc', ['isRowGroupRecord', 'isAggregateRecord']);
return $xeTable.isAggregateRecord(row);
},
isRowGroupExpandByRow(row) {
warnLog('vxe.error.delFunc', ['isRowGroupExpandByRow', 'isAggregateExpandByRow']);
return $xeTable.isAggregateExpandByRow(row);
},
isAggregateRecord(row) {
const { isRowGroupStatus } = reactData;
return isRowGroupStatus && row.isAggregate;
},
getAggregateContentByRow(row) {
const { isRowGroupStatus } = reactData;
return isRowGroupStatus && row && row.isAggregate ? row.groupContent : '';
},
getAggregateRowChildren(row) {
const aggregateOpts = computeAggregateOpts.value;
const { childrenField, mapChildrenField } = aggregateOpts;
const { isRowGroupStatus } = reactData;
return isRowGroupStatus && row && row.isAggregate && childrenField && mapChildrenField ? (row[mapChildrenField] || []) : [];
},
refreshAggregateCalcValues() {
updateGroupData();
return nextTick();
},
isAggregateExpandByRow(row) {
const { rowGroupExpandedFlag } = reactData;
const { rowGroupExpandedMaps } = internalData;
return !!rowGroupExpandedFlag && !!rowGroupExpandedMaps[getRowid($xeTable, row)];
},
setRowGroupExpand(rows, expanded) {
if (rows) {
if (!XEUtils.isArray(rows)) {
rows = [rows];
}
return handleRowGroupVirtualExpand(rows, expanded);
}
return nextTick();
},
setRowGroupExpandByField(groupFields, expanded) {
const { isRowGroupStatus } = reactData;
const aggregateOpts = computeAggregateOpts.value;
const { childrenField } = aggregateOpts;
if (groupFields) {
if (!XEUtils.isArray(groupFields)) {
groupFields = [groupFields];
}
if (isRowGroupStatus) {
const rows = [];
const gfKeys = {};
groupFields.forEach(groupField => {
gfKeys[groupField] = true;
});
XEUtils.eachTree(internalData.afterGroupFullData, (row) => {
if (row.isAggregate && gfKeys[row.groupField]) {
rows.push(row);
}
}, { children: childrenField });
if (rows.length) {
return handleRowGroupVirtualExpand(rows, expanded);
}
}
}
return nextTick();
},
setAllRowGroupExpand(expanded) {
const { tableFullGroupData } = internalData;
const aggregateOpts = computeAggregateOpts.value;
const { mapChildrenField } = aggregateOpts;
const rgExpandedMaps = {};
if (expanded && mapChildrenField) {
XEUtils.eachTree(tableFullGroupData, (row) => {
if (row[mapChildrenField] && row[mapChildrenField].length) {
rgExpandedMaps[getRowid($xeTable, row)] = row;
}
}, { children: mapChildrenField });
}
internalData.rowGroupExpandedMaps = rgExpandedMaps;
handleVirtualTreeToList();
$xeTable.handleTableData();
updateAfterDataIndex();
reactData.rowGroupExpandedFlag++;
return handleLazyRecalculate(true, true, true);
},
clearRowGroupExpand() {
internalData.rowGroupExpandedMaps = {};
handleVirtualTreeToList();
$xeTable.handleTableData();
updateAfterDataIndex();
reactData.rowGroupExpandedFlag++;
return handleLazyRecalculate(true, true, true);
},
getTreeExpandRecords() {
const rest = [];
XEUtils.each(internalData.treeExpandedMaps, item => {
if (item) {
rest.push(item);
}
});
return rest;
},
/**
* 判断树节点是否懒加载完成
* @param {Row} row 行对象
*/
isTreeExpandLoaded(row) {
const { fullAllDataRowIdData } = internalData;
const rowRest = fullAllDataRowIdData[getRowid($xeTable, row)];
return rowRest && !!rowRest.treeLoaded;
},
clearTreeExpandLoaded(rows) {
const { fullAllDataRowIdData, treeExpandedMaps } = internalData;
const treeOpts = computeTreeOpts.value;
const { transform } = treeOpts;
if (rows) {
if (!XEUtils.isArray(rows)) {
rows = [rows];
}
rows.forEach((row) => {
const rowid = getRowid($xeTable, row);
const rowRest = fullAllDataRowIdData[rowid];
if (rowRest) {
rowRest.treeLoaded = false;
if (treeExpandedMaps[rowid]) {
delete treeExpandedMaps[rowid];
}
}
});
}
else {
XEUtils.each(fullAllDataRowIdData, (rowRest) => {
rowRest.treeLoaded = false;
});
internalData.treeExpandedMaps = {};
}
if (transform) {
handleVirtualTreeToList();
$xeTable.handleTableData();
}
reactData.treeExpandedFlag++;
return nextTick();
},
/**
* 重新懒加载树节点,并展开该节点
* @param {Row} row 行对象
*/
reloadTreeExpand(row) {
const { treeExpandLazyLoadedMaps } = internalData;
const treeOpts = computeTreeOpts.value;
const hasChildField = treeOpts.hasChild || treeOpts.hasChildField;
const { transform, lazy } = treeOpts;
const rowid = getRowid($xeTable, row);
if (lazy && row[hasChildField] && !treeExpandLazyLoadedMaps[rowid]) {
return $xeTable.clearTreeExpandLoaded(row).then(() => {
return handleAsyncTreeExpandChilds(row);
}).then(() => {
if (transform) {
handleVirtualTreeToList();
$xeTable.handleTableData();
}
reactData.treeExpandedFlag++;
}).then(() => {
return $xeTable.recalculate();
});
}
return nextTick();
},
reloadTreeChilds(row) {
warnLog('vxe.error.delFunc', ['reloadTreeChilds', 'reloadTreeExpand']);
// 即将废弃
return $xeTable.reloadTreeExpand(row);
},
/**
* 切换/展开树节点
*/
toggleTreeExpand(row) {
return $xeTable.setTreeExpand(row, !$xeTable.isTreeExpandByRow(row));
},
/**
* 设置所有树节点的展开与否
* @param {Boolean} expanded 是否展开
*/
setAllTreeExpand(expanded) {
const { tableFullTreeData } = internalData;
const treeOpts = computeTreeOpts.value;
const { transform, lazy } = treeOpts;
const childrenField = treeOpts.children || treeOpts.childrenField;
const expandeds = [];
XEUtils.eachTree(tableFullTreeData, (row) => {
const rowChildren = row[childrenField];
if (lazy || (rowChildren && rowChildren.length)) {
expandeds.push(row);
}
}, { children: childrenField });
return $xeTable.setTreeExpand(expandeds, expanded).then(() => {
if (transform) {
handleVirtualTreeToList();
reactData.treeExpandedFlag++;
return $xeTable.recalculate();
}
});
},
/**
* 设置展开树形节点,二个参数设置这一行展开与否
* 支持单行
* 支持多行
* @param {Array/Row} rows 行数据
* @param {Boolean} expanded 是否展开
*/
setTreeExpand(rows, expanded) {
const treeOpts = computeTreeOpts.value;
const { transform } = treeOpts;
if (rows) {
if (!XEUtils.isArray(rows)) {
rows = [rows];
}
if (rows.length) {
// 如果为虚拟树
if (transform) {
return handleVirtualTreeExpand(rows, expanded);
}
else {
return handleBaseTreeExpand(rows, expanded);
}
}
}
return nextTick();
},
/**
* 判断行是否为树形节点展开状态
* @param {Row} row 行对象
*/
isTreeExpandByRow(row) {
const { treeExpandedFlag } = reactData;
const { treeExpandedMaps } = internalData;
return !!treeExpandedFlag && !!treeExpandedMaps[getRowid($xeTable, row)];
},
/**
* 手动清空树形节点的展开状态,数据会恢复成未展开的状态
*/
clearTreeExpand() {
const { tableFullTreeData } = internalData;
const treeOpts = computeTreeOpts.value;
const childrenField = treeOpts.children || treeOpts.childrenField;
const { transform, reserve } = treeOpts;
const expList = $xeTable.getTreeExpandRecords();
internalData.treeExpandedMaps = {};
if (reserve) {
XEUtils.eachTree(tableFullTreeData, row => handleTreeExpandReserve(row, false), { children: childrenField });
}
return $xeTable.handleTableData().then(() => {
if (transform) {
handleVirtualTreeToList();
$xeTable.handleTableData();
}
reactData.treeExpandedFlag++;
}).then(() => {
updateTreeLineStyle();
if (expList.length) {
return $xeTable.recalculate();
}
});
},
clearTreeExpandReserve() {
internalData.treeExpandedReserveRowMap = {};
return nextTick();
},
/**
* 获取表格的滚动状态
*/
getScroll() {
return $xeTable.getScrollData();
},
/**
* 获取表格的滚动数据
*/
getScrollData() {
const { scrollXLoad, scrollYLoad, scrollbarHeight, scrollbarWidth } = reactData;
const { elemStore } = internalData;
const bodyScrollElem = getRefElem(elemStore['main-body-scroll']);
const scrollTop = bodyScrollElem ? bodyScrollElem.scrollTop : 0;
const scrollLeft = bodyScrollElem ? bodyScrollElem.scrollLeft : 0;
const clientHeight = bodyScrollElem ? bodyScrollElem.clientHeight : 0;
const clientWidth = bodyScrollElem ? bodyScrollElem.clientWidth : 0;
const scrollHeight = bodyScrollElem ? bodyScrollElem.scrollHeight : 0;
const scrollWidth = bodyScrollElem ? bodyScrollElem.scrollWidth : 0;
const isTop = scrollTop <= 0;
const isBottom = scrollTop + clientHeight >= scrollHeight;
const isLeft = scrollLeft <= 0;
const isRight = scrollLeft + clientWidth >= scrollWidth;
return {
virtualX: scrollXLoad,
virtualY: scrollYLoad,
isTop,
isBottom,
isLeft,
isRight,
scrollbarHeight,
scrollbarWidth,
scrollTop,
scrollLeft,
scrollHeight,
scrollWidth,
clientHeight,
clientWidth
};
},
/**
* 如果有滚动条,则滚动到对应的位置
*/
scrollTo(scrollLeft, scrollTop) {
const { elemStore } = internalData;
const headerScrollElem = getRefElem(elemStore['main-header-scroll']);
const bodyScrollElem = getRefElem(elemStore['main-body-scroll']);
const footerScrollElem = getRefElem(elemStore['main-footer-scroll']);
const leftScrollElem = getRefElem(elemStore['left-body-scroll']);
const rightScrollElem = getRefElem(elemStore['right-body-scroll']);
const xHandleEl = refScrollXHandleElem.value;
const yHandleEl = refScrollYHandleElem.value;
internalData.intoRunScroll = true;
if (scrollLeft) {
if (!XEUtils.isNumber(scrollLeft)) {
scrollTop = scrollLeft.top;
scrollLeft = scrollLeft.left;
}
}
if (XEUtils.isNumber(scrollLeft)) {
setScrollLeft(xHandleEl, scrollLeft);
setScrollLeft(bodyScrollElem, scrollLeft);
setScrollLeft(headerScrollElem, scrollLeft);
setScrollLeft(footerScrollElem, scrollLeft);
if (reactData.scrollXLoad) {
loadScrollXData();
}
}
if (XEUtils.isNumber(scrollTop)) {
setScrollTop(yHandleEl, scrollTop);
setScrollTop(bodyScrollElem, scrollTop);
setScrollTop(leftScrollElem, scrollTop);
setScrollTop(rightScrollElem, scrollTop);
if (reactData.scrollYLoad) {
loadScrollYData();
}
}
return new Promise(resolve => {
setTimeout(() => {
nextTick(() => {
internalData.intoRunScroll = false;
resolve();
});
}, (reactData.scrollXLoad || reactData.scrollYLoad) ? 30 : 0);
});
},
/**
* 如果有滚动条,则滚动到对应的行
*/
scrollToRow(rowOrRowid, fieldOrColumn, options) {
const { isAllOverflow, scrollYLoad, scrollXLoad } = reactData;
const { fullAllDataRowIdData, _sToTime } = internalData;
const rest = [];
let row;
if (XEUtils.isString(rowOrRowid) || XEUtils.isNumber(rowOrRowid)) {
const rowid = rowOrRowid;
const rowRest = rowid ? fullAllDataRowIdData[rowid] : null;
if (rowRest) {
row = rowRest.row;
}
}
else {
row = rowOrRowid;
}
if (row) {
if (props.treeConfig) {
rest.push($xeTable.scrollToTreeRow(row));
}
else {
rest.push(rowToVisible($xeTable, row));
}
}
if (fieldOrColumn) {
rest.push(handleScrollToRowColumn(fieldOrColumn, row, options));
}
if (_sToTime) {
clearTimeout(_sToTime);
}
return Promise.all(rest).then(() => {
if (row) {
if (!isAllOverflow && (scrollYLoad || scrollXLoad)) {
calcCellHeight();
calcCellWidth();
// 可视区被渲染后位置被偏移
internalData._sToTime = setTimeout(() => {
internalData._sToTime = undefined;
if (scrollYLoad) {
if (props.treeConfig) {
$xeTable.scrollToTreeRow(row);
}
else {
rowToVisible($xeTable, row);
}
}
if (scrollXLoad && fieldOrColumn) {
handleScrollToRowColumn(fieldOrColumn, row, options);
}
}, 350);
}
return nextTick();
}
});
},
/**
* 如果有滚动条,则滚动到第一行
*/
scrollToStartRow(fieldOrColumn, options) {
const { afterFullData } = internalData;
return $xeTable.scrollToRow(afterFullData[0], fieldOrColumn, options);
},
/**
* 如果有滚动条,则滚动到最后一行
*/
scrollToEndRow(fieldOrColumn, options) {
const { afterFullData } = internalData;
return $xeTable.scrollToRow(afterFullData[afterFullData.length - 1], fieldOrColumn, options);
},
/**
* 如果有滚动条,则滚动到对应的列
*/
scrollToColumn(fieldOrColumn, options) {
return handleScrollToRowColumn(fieldOrColumn, null, options);
},
/**
* 如果有滚动条,则滚动到第一列
*/
scrollToStartColumn(options) {
const { visibleColumn } = internalData;
return $xeTable.scrollToColumn(visibleColumn[0], options);
},
/**
* 如果有滚动条,则滚动到最后一列
*/
scrollToEndColumn(options) {
const { visibleColumn } = internalData;
return $xeTable.scrollToColumn(visibleColumn[visibleColumn.length - 1], options);
},
/**
* 手动清除滚动相关信息,还原到初始状态
*/
clearScroll() {
const { elemStore, scrollXStore, scrollYStore } = internalData;
const headerScrollElem = getRefElem(elemStore['main-header-scroll']);
const bodyScrollElem = getRefElem(elemStore['main-body-scroll']);
const footerScrollElem = getRefElem(elemStore['main-footer-scroll']);
const leftScrollElem = getRefElem(elemStore['left-body-scroll']);
const rightScrollElem = getRefElem(elemStore['right-body-scroll']);
const xHandleEl = refScrollXHandleElem.value;
const yHandleEl = refScrollYHandleElem.value;
internalData.intoRunScroll = true;
setScrollLeft(xHandleEl, 0);
setScrollLeft(bodyScrollElem, 0);
setScrollLeft(headerScrollElem, 0);
setScrollLeft(footerScrollElem, 0);
setScrollTop(yHandleEl, 0);
setScrollTop(bodyScrollElem, 0);
setScrollTop(leftScrollElem, 0);
setScrollTop(rightScrollElem, 0);
scrollXStore.startIndex = 0;
scrollXStore.visibleStartIndex = 0;
scrollXStore.endIndex = scrollXStore.visibleSize;
scrollXStore.visibleEndIndex = scrollXStore.visibleSize;
scrollYStore.startIndex = 0;
scrollYStore.visibleStartIndex = 0;
scrollYStore.endIndex = scrollYStore.visibleSize;
scrollYStore.visibleEndIndex = scrollYStore.visibleSize;
return nextTick().then(() => {
internalData.lastScrollLeft = 0;
internalData.lastScrollTop = 0;
internalData.intoRunScroll = false;
});
},
/**
* 更新表尾合计
*/
updateFooter() {
const { showFooter, footerData, footerMethod } = props;
const { visibleColumn, afterFullData } = internalData;
let footData = [];
if (showFooter && footerData && footerData.length) {
footData = footerData.slice(0);
}
else if (showFooter && footerMethod) {
footData = visibleColumn.length ? footerMethod({ columns: visibleColumn, data: afterFullData, $table: $xeTable, $grid: $xeGrid, $gantt: $xeGantt }) : [];
}
reactData.footerTableData = footData;
$xeTable.clearFooterFormatterCache();
$xeTable.handleUpdateFooterMerge();
$xeTable.dispatchEvent('footer-data-change', {
visibleColumn: internalData.visibleColumn,
footData
}, null);
return nextTick();
},
/**
* 更新列状态 updateStatus({ row, column }, cellValue)
* 如果组件值 v-model 发生 change 时,调用改函数用于更新某一列编辑状态
* 如果单元格配置了校验规则,则会进行校验
*/
updateStatus(slotParams, cellValue) {
return nextTick().then(() => {
const { editRules } = props;
const { isActivated } = internalData;
if (isActivated && slotParams && editRules) {
return $xeTable.handleCellRuleUpdateStatus('change', slotParams, cellValue);
}
});
},
/**
* 设置合并单元格 [{ row: Row|number, column: ColumnInfo|number, rowspan: number, colspan: number }]
*/
setMergeCells(merges) {
if (props.spanMethod) {
errLog('vxe.error.errConflicts', ['merge-cells', 'span-method']);
}
handleBodyMerge(merges);
$xeTable.handleUpdateBodyMerge();
return nextTick().then(() => {
const { expandColumn } = reactData;
const { mergeBodyList } = internalData;
if (expandColumn && mergeBodyList.length) {
warnLog('vxe.error.errConflicts', ['type=expand', 'merge-cells | span-method']);
}
$xeTable.updateCellAreas();
return updateStyle();
});
},
/**
* 移除单元格合并 [{row:Row|number, col:ColumnInfo|number}]
*/
removeMergeCells(merges) {
if (props.spanMethod) {
errLog('vxe.error.errConflicts', ['merge-cells', 'span-method']);
}
const rest = removeBodyMerges(merges);
$xeTable.handleUpdateBodyMerge();
return nextTick().then(() => {
$xeTable.updateCellAreas();
updateStyle();
return rest;
});
},
/**
* 获取所有被合并的单元格
*/
getMergeCells() {
return internalData.mergeBodyList.slice(0);
},
/**
* 清除所有单元格合并
*/
clearMergeCells() {
internalData.mergeBodyList = [];
internalData.mergeBodyMaps = {};
internalData.mergeBodyCellMaps = {};
internalData.mergeBodyRowMaps = {};
internalData.mergeBodyColMaps = {};
reactData.mergeBodyFlag++;
return nextTick().then(() => {
return updateStyle();
});
},
setMergeHeaderCells(merges) {
handleHeaderMerge(merges);
$xeTable.handleUpdateHeaderMerge();
return nextTick().then(() => {
return updateStyle();
});
},
/**
* 移除表头单元格合并 [{row:Row|number, col:ColumnInfo|number}]
*/
removeMergeHeaderCells(merges) {
const rest = removeHeaderMerges(merges);
$xeTable.handleUpdateHeaderMerge();
return nextTick().then(() => {
updateStyle();
return rest;
});
},
/**
* 获取所有被合并的表头单元格
*/
getMergeHeaderCells() {
return internalData.mergeHeaderList.slice(0);
},
/**
* 清除所有表头单元格合并
*/
clearMergeHeaderCells() {
internalData.mergeHeaderList = [];
internalData.mergeHeaderMaps = {};
internalData.mergeHeaderCellMaps = {};
internalData.mergeHeaderRowMaps = {};
internalData.mergeBodyColMaps = {};
reactData.mergeHeadFlag++;
return nextTick().then(() => {
return updateStyle();
});
},
setMergeFooterCells(merges) {
if (props.footerSpanMethod) {
errLog('vxe.error.errConflicts', ['merge-footer-cells | merge-footer-items', 'footer-span-method']);
}
handleFooterMerge(merges);
$xeTable.handleUpdateFooterMerge();
return nextTick().then(() => {
return updateStyle();
});
},
setMergeFooterItems(merges) {
// errLog('vxe.error.delFunc', ['setMergeFooterItems', 'setMergeFooterCells'])
return $xeTable.setMergeFooterCells(merges);
},
removeMergeFooterCells(merges) {
if (props.footerSpanMethod) {
errLog('vxe.error.errConflicts', ['merge-footer-cells | merge-footer-items', 'footer-span-method']);
}
const rest = removeFooterMerges(merges);
$xeTable.handleUpdateFooterMerge();
return nextTick().then(() => {
updateStyle();
return rest;
});
},
removeMergeFooterItems(merges) {
// errLog('vxe.error.delFunc', ['removeMergeFooterItems', 'removeMergeFooterCells'])
return $xeTable.removeMergeFooterCells(merges);
},
/**
* 获取所有被合并的表尾
*/
getMergeFooterCells() {
return internalData.mergeFooterList.slice(0);
},
getMergeFooterItems() {
// errLog('vxe.error.delFunc', ['getMergeFooterItems', 'getMergeFooterCells'])
return $xeTable.getMergeFooterCells();
},
/**
* 清除所有表尾合并
*/
clearMergeFooterCells() {
internalData.mergeFooterList = [];
internalData.mergeFooterMaps = {};
internalData.mergeFooterCellMaps = {};
internalData.mergeFooterRowMaps = {};
internalData.mergeFooterColMaps = {};
reactData.mergeFootFlag++;
return nextTick().then(() => {
return updateStyle();
});
},
clearMergeFooterItems() {
// errLog('vxe.error.delFunc', ['clearMergeFooterItems', 'clearMergeFooterCells'])
return $xeTable.clearMergeFooterCells();
},
updateCellAreas() {
const { mouseConfig } = props;
const mouseOpts = computeMouseOpts.value;
if (mouseConfig && mouseOpts.area && $xeTable.handleRecalculateCellAreaEvent) {
return $xeTable.handleRecalculateCellAreaEvent();
}
return nextTick();
},
undo() {
return $xeTable.handleUndoStackEvent(null);
},
redo() {
return $xeTable.handleRedoStackEvent(null);
},
clearHistory() {
return $xeTable.handleClearStack();
},
/**
* 用于 custom-config,用于手动恢复自定义列设置信息,恢复表格重置为初始状态
* @param storeData
* @returns
*/
setCustomStoreData(storeData) {
if (!storeData) {
return nextTick();
}
const customOpts = computeCustomOpts.value;
const { checkMethod } = customOpts;
// 重置状态
clearTableAllStatus($xeTable);
// 恢复列
const allCols = [];
XEUtils.eachTree(internalData.collectColumn, (column) => {
column.resizeWidth = 0;
column.fixed = column.defaultFixed;
column.renderSortNumber = column.sortNumber;
column.parentId = column.defaultParentId;
if (!checkMethod || checkMethod({ $table: $xeTable, column })) {
column.visible = column.defaultVisible;
}
column.align = column.defaultAlign;
column.headerAlign = column.defaultHeaderAlign;
column.footerAlign = column.defaultFooterAlign;
column.aggFunc = column.defaultAggFunc;
column.renderAggFn = column.defaultAggFunc;
column.renderResizeWidth = column.renderWidth;
allCols.push(column);
});
const newCollectCols = XEUtils.toArrayTree(XEUtils.orderBy(allCols, 'renderSortNumber'), { key: 'id', parentKey: 'parentId', children: 'children' });
internalData.collectColumn = newCollectCols;
internalData.tableFullColumn = getColumnList(newCollectCols);
reactData.updateColFlag++;
reactData.isColLoading = true;
initColumnHierarchy();
return Promise.resolve(handleCustomRestore(storeData)).then(() => {
return buildColumnInfo();
}).then(() => {
// 恢复数据聚合分组
const { isRowGroupStatus, rowGroupList } = reactData;
if (isRowGroupStatus && !!$xeTable.handlePivotTableAggData) {
const rowGroupFields = computeRowGroupFields.value;
if (rowGroupFields ? rowGroupFields.length : rowGroupList.length) {
if (rowGroupFields && rowGroupFields.length) {
$xeTable.setRowGroups(rowGroupFields);
}
else {
$xeTable.clearRowGroups();
}
}
else {
$xeTable.handleUpdateAggData();
}
}
});
},
/**
* 用于 custom-config,用于获取自定义列设置信息,用于自定义保持
* @returns
*/
getCustomStoreData() {
const { id } = props;
const customOpts = computeCustomOpts.value;
const { isRowGroupStatus, rowGroupList } = reactData;
const { fullColumnFieldData, collectColumn } = internalData;
const { storage, checkMethod } = customOpts;
const { isCustomAlign, isCustomHeaderAlign, isCustomFooterAlign, isCustomResizable, isCustomVisible, isCustomFixed, isCustomSort, isCustomAggGroup, isCustomAggFunc, isCustomPager } = handleCustomStoreConfig($xeTable);
const alignData = {};
const headerAlignData = {};
const footerAlignData = {};
const resizableData = {};
const sortData = [];
const visibleData = {};
const fixedData = {};
const aggGroupData = {};
const aggFuncData = {};
const storeData = {
pagerData: isCustomPager && $xeGGWrapper && $xeGGWrapper.getCustomPagerData ? $xeGGWrapper.getCustomPagerData() : undefined,
alignData: undefined,
headerAlignData: undefined,
footerAlignData: undefined,
resizableData: undefined,
sortData: undefined,
visibleData: undefined,
fixedData: undefined,
aggGroupData: undefined,
aggFuncData: undefined
};
if (!id) {
if (storage) {
errLog('vxe.error.reqProp', ['id']);
}
return storeData;
}
let hasAlign = 0;
let hasHeaderAlign = 0;
let hasFooterAlign = 0;
let hasResizable = 0;
let hasSort = 0;
let hasFixed = 0;
let hasVisible = 0;
let hasAggFunc = 0;
const sortMaps = {};
XEUtils.eachTree(collectColumn, (column, index, items, path, parentColumn) => {
const colKey = column.getKey();
if (!colKey) {
errLog('vxe.error.reqProp', [`${column.getTitle() || column.type || ''} -> column.field=?`]);
return;
}
if (parentColumn) {
if (isCustomSort) {
const pColKey = parentColumn.getKey();
const psObj = sortMaps[pColKey];
hasSort = 1;
if (psObj) {
const sObj = { k: colKey };
sortMaps[colKey] = sObj;
if (!psObj.c) {
psObj.c = [];
}
psObj.c.push(sObj);
}
}
}
else {
if (isCustomSort) {
hasSort = 1;
const sObj = { k: colKey };
sortMaps[colKey] = sObj;
sortData.push(sObj);
}
// 只支持一级
if (isCustomFixed && (column.fixed || '') !== (column.defaultFixed || '')) {
hasFixed = 1;
fixedData[colKey] = column.fixed;
}
}
if (isCustomAlign && column.align) {
hasAlign = 1;
alignData[colKey] = column.align;
}
if (isCustomHeaderAlign && column.headerAlign) {
hasHeaderAlign = 1;
headerAlignData[colKey] = column.headerAlign;
}
if (isCustomFooterAlign && column.footerAlign) {
hasFooterAlign = 1;
footerAlignData[colKey] = column.footerAlign;
}
if (isCustomResizable && column.resizeWidth) {
hasResizable = 1;
resizableData[colKey] = column.renderWidth;
}
if (isCustomVisible && (!checkMethod || checkMethod({ $table: $xeTable, column }))) {
if (!column.visible && column.defaultVisible) {
hasVisible = 1;
visibleData[colKey] = false;
}
else if (column.visible && !column.defaultVisible) {
hasVisible = 1;
visibleData[colKey] = true;
}
}
if (isCustomAggFunc && (column.aggFunc || '') !== (column.defaultAggFunc || '')) {
hasAggFunc = 1;
aggFuncData[colKey] = column.aggFunc;
}
});
if (hasAlign) {
storeData.alignData = alignData;
}
if (hasHeaderAlign) {
storeData.headerAlignData = headerAlignData;
}
if (hasFooterAlign) {
storeData.footerAlignData = footerAlignData;
}
if (hasResizable) {
storeData.resizableData = resizableData;
}
if (hasSort) {
storeData.sortData = sortData;
}
if (hasFixed) {
storeData.fixedData = fixedData;
}
if (hasVisible) {
storeData.visibleData = visibleData;
}
if (isCustomAggGroup && isRowGroupStatus) {
rowGroupList.forEach(aggConf => {
const colRest = fullColumnFieldData[aggConf.field];
if (colRest) {
aggGroupData[colRest.column.getKey()] = true;
}
});
storeData.aggGroupData = aggGroupData;
}
if (hasAggFunc) {
storeData.aggFuncData = aggFuncData;
}
return storeData;
},
focus() {
internalData.isActivated = true;
return nextTick();
},
blur() {
internalData.isActivated = false;
return nextTick();
},
/**
* 已废弃,被 connectToolbar 替换
* @deprecated
*/
connect($toolbar) {
return $xeTable.connectToolbar($toolbar);
},
/**
* 连接工具栏
* @param $toolbar
*/
connectToolbar($toolbar) {
if ($toolbar) {
$xeToolbar = $toolbar;
$xeToolbar.syncUpdate({ collectColumn: internalData.collectColumn, $table: $xeTable });
}
else {
errLog('vxe.error.barUnableLink');
}
return nextTick();
}
};
/**
* 全局按下事件处理
*/
const handleGlobalMousedownEvent = (evnt) => {
const { editStore, ctxMenuStore, customStore } = reactData;
const { mouseConfig, editRules } = props;
const el = refElem.value;
const editOpts = computeEditOpts.value;
const validOpts = computeValidOpts.value;
const areaOpts = computeAreaOpts.value;
const { actived } = editStore;
const $validTooltip = refValidTooltip.value;
const tableFilter = refTableFilter.value;
const tableCustom = refTableCustom.value;
const tableMenu = refTableMenu.value;
// 筛选
if (tableFilter) {
if (getEventTargetNode(evnt, el, 'vxe-cell--filter').flag) {
// 如果点击了筛选按钮
}
else if (getEventTargetNode(evnt, tableFilter.getRefMaps().refElem.value).flag) {
// 如果点击筛选容器
}
else {
if (!getEventTargetNode(evnt, document.body, 'vxe-table--ignore-clear').flag) {
$xeTable.preventEvent(evnt, 'event.clearFilter', internalData._currFilterParams, $xeTable.closeFilter);
}
}
}
// 自定义列
if (tableCustom) {
if (customStore.btnEl === evnt.target || getEventTargetNode(evnt, document.body, 'vxe-toolbar-custom-target').flag) {
// 如果点击了自定义列按钮
}
else if (getEventTargetNode(evnt, tableCustom.getRefMaps().refElem.value).flag) {
// 如果点击自定义列容器
}
else {
if (!getEventTargetNode(evnt, document.body, 'vxe-table--ignore-clear').flag) {
if (customStore.visible && $xeTable.closeCustom) {
$xeTable.preventEvent(evnt, 'event.clearCustom', {}, () => {
$xeTable.closeCustom();
$xeTable.dispatchEvent('custom', { type: 'close' }, evnt);
});
}
}
}
}
// 如果已激活了编辑状态
if (actived.row) {
if (!(editOpts.autoClear === false)) {
// 如果是激活状态,点击了单元格之外
const cell = actived.args.cell;
if ((!cell || !getEventTargetNode(evnt, cell).flag)) {
if ($validTooltip && getEventTargetNode(evnt, $validTooltip.$el).flag) {
// 如果是激活状态,且点击了校验提示框
}
else if (!internalData._lastCallTime || internalData._lastCallTime + 50 < Date.now()) {
// 如果是激活状态,点击了单元格之外
if (!getEventTargetNode(evnt, document.body, 'vxe-table--ignore-clear').flag) {
// 如果手动调用了激活单元格,避免触发源被移除后导致重复关闭
$xeTable.preventEvent(evnt, 'event.clearEdit', actived.args, () => {
let isClear;
if (editOpts.mode === 'row') {
const rowTargetNode = getEventTargetNode(evnt, el, 'vxe-body--row');
const rowNodeRest = rowTargetNode.flag ? $xeTable.getRowNode(rowTargetNode.targetElem) : null;
// row 方式,如果点击了不同行
isClear = rowNodeRest ? !$xeTable.eqRow(rowNodeRest.item, actived.args.row) : false;
}
else {
// cell 方式,如果是非编辑列
isClear = !getEventTargetNode(evnt, el, 'col--edit').flag;
}
// 如果点击表头行,则清除激活状态
if (!isClear) {
isClear = getEventTargetNode(evnt, el, 'vxe-header--row').flag;
}
// 如果点击表尾行,则清除激活状态
if (!isClear) {
isClear = getEventTargetNode(evnt, el, 'vxe-footer--row').flag;
}
// 如果固定了高度且点击了行之外的空白处,则清除激活状态
if (!isClear && props.height && !reactData.overflowY) {
const bodyWrapperElem = evnt.target;
if (hasClass(bodyWrapperElem, 'vxe-table--body-wrapper')) {
isClear = evnt.offsetY < bodyWrapperElem.clientHeight;
}
}
if (isClear ||
// 如果点击了当前表格之外
!getEventTargetNode(evnt, el).flag) {
setTimeout(() => {
$xeTable.handleClearEdit(evnt).then(() => {
// 如果存在校验,点击了表格之外则清除
if (!internalData.isActivated && editRules && validOpts.autoClear) {
reactData.validErrorMaps = {};
}
});
});
}
});
}
}
}
}
}
else if (mouseConfig) {
if (!getEventTargetNode(evnt, el).flag && !($xeGGWrapper && getEventTargetNode(evnt, $xeGGWrapper.getRefMaps().refElem.value).flag) && !(tableMenu && getEventTargetNode(evnt, tableMenu.getRefMaps().refElem.value).flag) && !($xeToolbar && getEventTargetNode(evnt, $xeToolbar.getRefMaps().refElem.value).flag)) {
if ($xeTable.clearSelected) {
$xeTable.clearSelected();
}
if (areaOpts.autoClear) {
if ($xeTable.getCellAreas) {
const cellAreas = $xeTable.getCellAreas();
if (cellAreas && cellAreas.length && !getEventTargetNode(evnt, document.body, 'vxe-table--ignore-areas-clear').flag) {
$xeTable.preventEvent(evnt, 'event.clearAreas', {}, () => {
$xeTable.clearCellAreas();
$xeTable.clearCopyCellArea();
dispatchEvent('clear-cell-area-selection', { cellAreas }, evnt);
});
}
}
}
}
}
// 如果配置了快捷菜单且,点击了其他地方则关闭
if ($xeTable.closeMenu) {
if (ctxMenuStore.visible && tableMenu && !getEventTargetNode(evnt, tableMenu.getRefMaps().refElem.value).flag) {
$xeTable.closeMenu();
}
}
if (!(actived.row && getEventTargetNode(evnt, document.body, 'vxe-table--ignore-clear').flag)) {
const isActivated = getEventTargetNode(evnt, $xeGGWrapper ? $xeGGWrapper.getRefMaps().refElem.value : el).flag;
// 如果存在校验,点击了表格之外则清除
if (!isActivated && editRules && validOpts.autoClear) {
reactData.validErrorMaps = {};
}
// 最后激活的表格
internalData.isActivated = isActivated;
}
};
/**
* 窗口失焦事件处理
*/
const handleGlobalBlurEvent = () => {
$xeTable.closeFilter();
if ($xeTable.closeMenu) {
$xeTable.closeMenu();
}
};
const reUpdateCustomStyleEvent = (evnt) => {
const { customStore } = reactData;
const customOpts = computeCustomOpts.value;
const { popupOptions } = customOpts;
const { transfer } = popupOptions || {};
if (transfer && customStore.visible) {
const tableCustom = refTableCustom.value;
if (tableCustom && $xeTable.handleCustomStyle && !checkTargetElement(evnt.target, [tableCustom.getRefMaps().refElem.value], evnt.currentTarget)) {
$xeTable.handleCustomStyle().then(() => {
$xeTable.handleCustomStyle();
});
}
}
};
const handleGlobalScrollEvent = (evnt) => {
reUpdateCustomStyleEvent(evnt);
};
/**
* 全局滚动事件
*/
const handleGlobalMousewheelEvent = () => {
$xeTable.closeTooltip();
if ($xeTable.closeMenu) {
$xeTable.closeMenu();
}
};
/**
* 表格键盘事件
*/
const keydownEvent = (evnt) => {
const { mouseConfig, keyboardConfig } = props;
const { filterStore, ctxMenuStore, editStore } = reactData;
const mouseOpts = computeMouseOpts.value;
const keyboardOpts = computeKeyboardOpts.value;
const { actived } = editStore;
const isEsc = globalEvents.hasKey(evnt, GLOBAL_EVENT_KEYS.ESCAPE);
if (isEsc) {
$xeTable.preventEvent(evnt, 'event.keydown', null, () => {
dispatchEvent('keydown-start', {}, evnt);
if (keyboardConfig && mouseConfig && mouseOpts.area && $xeTable.handleKdClAreaEvent) {
$xeTable.handleKdClAreaEvent(evnt);
}
else if (actived.row || filterStore.visible || ctxMenuStore.visible) {
evnt.stopPropagation();
// 如果按下了 Esc 键,关闭快捷菜单、筛选
if ($xeTable.closeMenu) {
$xeTable.closeMenu();
}
$xeTable.closeFilter();
if (keyboardConfig && keyboardOpts.isEsc) {
// 如果是激活编辑状态,则取消编辑
if (actived.row) {
const params = actived.args;
$xeTable.handleClearEdit(evnt);
// 如果配置了选中功能,则为选中状态
if (mouseOpts.selected) {
nextTick(() => $xeTable.handleSelected(params, evnt));
}
}
}
}
dispatchEvent('keydown', {}, evnt);
dispatchEvent('keydown-end', {}, evnt);
});
}
};
const contextMenuEvent = (evnt) => {
dispatchEvent('context-menu', {}, evnt);
};
/**
* 全局键盘事件
*/
const handleGlobalKeydownEvent = (evnt) => {
// 该行为只对当前激活的表格有效
if (internalData.isActivated) {
$xeTable.preventEvent(evnt, 'event.keydown', null, () => {
const { mouseConfig, keyboardConfig, treeConfig, editConfig, highlightCurrentRow, highlightCurrentColumn } = props;
const { ctxMenuStore, editStore } = reactData;
const { afterFullData, visibleColumn, currentRow } = internalData;
const isContentMenu = computeIsContentMenu.value;
const bodyMenu = computeBodyMenu.value;
const keyboardOpts = computeKeyboardOpts.value;
const mouseOpts = computeMouseOpts.value;
const editOpts = computeEditOpts.value;
const treeOpts = computeTreeOpts.value;
const menuList = computeMenuList.value;
const rowOpts = computeRowOpts.value;
const columnOpts = computeColumnOpts.value;
const { isLastEnterAppendRow, beforeEnterMethod, enterMethod, isLastTabAppendRow, beforeTabMethod, tabMethod } = keyboardOpts;
const { selected, actived } = editStore;
const childrenField = treeOpts.children || treeOpts.childrenField;
const keyCode = evnt.keyCode;
const isProcess = globalEvents.hasKey(evnt, GLOBAL_EVENT_KEYS.PROCESS);
const isEsc = globalEvents.hasKey(evnt, GLOBAL_EVENT_KEYS.ESCAPE);
const hasBackspaceKey = globalEvents.hasKey(evnt, GLOBAL_EVENT_KEYS.BACKSPACE);
const isTab = globalEvents.hasKey(evnt, GLOBAL_EVENT_KEYS.TAB);
const isEnter = globalEvents.hasKey(evnt, GLOBAL_EVENT_KEYS.ENTER);
const isSpacebar = globalEvents.hasKey(evnt, GLOBAL_EVENT_KEYS.SPACEBAR);
const isLeftArrow = globalEvents.hasKey(evnt, GLOBAL_EVENT_KEYS.ARROW_LEFT);
const isUpArrow = globalEvents.hasKey(evnt, GLOBAL_EVENT_KEYS.ARROW_UP);
const isRightArrow = globalEvents.hasKey(evnt, GLOBAL_EVENT_KEYS.ARROW_RIGHT);
const isDwArrow = globalEvents.hasKey(evnt, GLOBAL_EVENT_KEYS.ARROW_DOWN);
const hasDeleteKey = globalEvents.hasKey(evnt, GLOBAL_EVENT_KEYS.DELETE);
const isY = globalEvents.hasKey(evnt, GLOBAL_EVENT_KEYS.Y);
const isZ = globalEvents.hasKey(evnt, GLOBAL_EVENT_KEYS.Z);
const isF2 = globalEvents.hasKey(evnt, GLOBAL_EVENT_KEYS.F2);
const isContextMenu = globalEvents.hasKey(evnt, GLOBAL_EVENT_KEYS.CONTEXT_MENU);
const isControlKey = hasControlKey(evnt);
const hasShiftKey = evnt.shiftKey;
const isAltKey = evnt.altKey;
const operArrow = isLeftArrow || isUpArrow || isRightArrow || isDwArrow;
const operCtxMenu = isContentMenu && ctxMenuStore.visible && (isEnter || isSpacebar || operArrow);
const isEditStatus = isEnableConf(editConfig) && actived.column && actived.row;
const beforeEditMethod = editOpts.beforeEditMethod || editOpts.activeMethod;
const selectRow = selected.row;
const selectColumn = selected.column;
if (operCtxMenu) {
// 如果配置了右键菜单; 支持方向键操作、回车
evnt.preventDefault();
if (ctxMenuStore.showChild && hasChildrenList(ctxMenuStore.selected)) {
$xeTable.moveCtxMenu(evnt, ctxMenuStore, 'selectChild', isLeftArrow, false, ctxMenuStore.selected.children);
}
else {
$xeTable.moveCtxMenu(evnt, ctxMenuStore, 'selected', isRightArrow, true, menuList);
}
}
else if (keyboardConfig && mouseConfig && mouseOpts.area && $xeTable.handleKdClAreaEvent) {
$xeTable.handleKdClAreaEvent(evnt);
}
else if (isEsc) {
// 如果按下了 Esc 键,关闭快捷菜单、筛选
if ($xeTable.closeMenu) {
$xeTable.closeMenu();
}
$xeTable.closeFilter();
if (keyboardConfig && keyboardOpts.isEsc) {
// 如果是激活编辑状态,则取消编辑
if (actived.row) {
const params = actived.args;
$xeTable.handleClearEdit(evnt);
// 如果配置了选中功能,则为选中状态
if (mouseOpts.selected) {
nextTick(() => $xeTable.handleSelected(params, evnt));
}
}
}
}
else if (isSpacebar && keyboardConfig && keyboardOpts.isChecked && selectRow && selectColumn && (selectColumn.type === 'checkbox' || selectColumn.type === 'radio')) {
// 空格键支持选中复选框
evnt.preventDefault();
if (selectColumn.type === 'checkbox') {
$xeTable.handleToggleCheckRowEvent(evnt, selected.args);
}
else {
$xeTable.triggerRadioRowEvent(evnt, selected.args);
}
}
else if (isF2 && isEnableConf(editConfig)) {
if (!isEditStatus) {
// 如果按下了 F2 键
if (selectRow && selectColumn) {
evnt.preventDefault();
$xeTable.handleEdit(selected.args, evnt);
}
}
}
else if (isContextMenu) {
// 如果按下上下文键
internalData._keyCtx = selectRow && selectColumn && bodyMenu.length;
clearTimeout(internalData.keyCtxTimeout);
internalData.keyCtxTimeout = setTimeout(() => {
internalData._keyCtx = false;
}, 1000);
}
else if (isEnter && !isAltKey && keyboardConfig && keyboardOpts.isEnter && (selectRow || actived.row || (treeConfig && (rowOpts.isCurrent || highlightCurrentRow) && currentRow))) {
// 退出选中
if (isControlKey) {
// 如果是激活编辑状态,则取消编辑
if (actived.row) {
const params = actived.args;
$xeTable.handleClearEdit(evnt);
// 如果配置了选中功能,则为选中状态
if (mouseOpts.selected) {
nextTick(() => {
$xeTable.handleSelected(params, evnt);
});
}
}
}
else {
// 如果是激活状态,退则出到上一行/下一行
if (selectRow || actived.row) {
const activeRow = selectRow || actived.row;
const activeColumn = selectColumn || actived.column;
if (activeColumn) {
const activeParams = selectRow ? selected.args : actived.args;
if (hasShiftKey) {
if (keyboardOpts.enterToTab) {
$xeTable.moveTabSelected(activeParams, hasShiftKey, evnt);
}
else {
$xeTable.moveEnterSelected(activeParams, isLeftArrow, true, isRightArrow, false, evnt);
}
}
else {
const _rowIndex = $xeTable.getVTRowIndex(activeRow);
const _columnIndex = $xeTable.getVTColumnIndex(activeColumn);
if (keyboardOpts.enterToTab) {
const ttrParams = {
row: activeRow,
rowIndex: $xeTable.getRowIndex(activeRow),
$rowIndex: $xeTable.getVMRowIndex(activeRow),
_rowIndex,
column: activeColumn,
columnIndex: $xeTable.getColumnIndex(activeColumn),
$columnIndex: $xeTable.getVMColumnIndex(activeColumn),
_columnIndex,
$table: $xeTable
};
if (!beforeTabMethod || beforeTabMethod(ttrParams) !== false) {
evnt.preventDefault();
// 最后一行按下Tab键,自动追加一行
if (isLastTabAppendRow) {
const newColumn = visibleColumn[0];
if (_rowIndex >= afterFullData.length - 1 && _columnIndex >= visibleColumn.length - 1) {
if (actived.row) {
$xeTable.handleClearEdit(evnt);
}
$xeTable.insertAt({}, -1).then(({ row: newRow }) => {
$xeTable.scrollToRow(newRow, newColumn);
$xeTable.handleSelected(Object.assign(Object.assign({}, activeParams), { row: newRow, column: newColumn }), evnt);
});
$xeTable.dispatchEvent('tab-append-row', ttrParams, evnt);
return;
}
}
if (tabMethod) {
tabMethod(ttrParams);
}
else {
$xeTable.moveTabSelected(activeParams, hasShiftKey, evnt);
}
}
}
else {
const etrParams = {
row: activeRow,
rowIndex: $xeTable.getRowIndex(activeRow),
$rowIndex: $xeTable.getVMRowIndex(activeRow),
_rowIndex,
column: activeColumn,
columnIndex: $xeTable.getColumnIndex(activeColumn),
$columnIndex: $xeTable.getVMColumnIndex(activeColumn),
_columnIndex,
$table: $xeTable
};
if (!beforeEnterMethod || beforeEnterMethod(etrParams) !== false) {
evnt.preventDefault();
// 最后一行按下回车键,自动追加一行
if (isLastEnterAppendRow) {
if (_rowIndex >= afterFullData.length - 1) {
$xeTable.insertAt({}, -1).then(({ row: newRow }) => {
$xeTable.scrollToRow(newRow, activeColumn);
$xeTable.handleSelected(Object.assign(Object.assign({}, activeParams), { row: newRow }), evnt);
});
$xeTable.dispatchEvent('enter-append-row', etrParams, evnt);
return;
}
}
if (enterMethod) {
enterMethod(etrParams);
}
else {
if (actived.row) {
$xeTable.handleClearEdit(evnt);
}
$xeTable.moveEnterSelected(activeParams, isLeftArrow, false, isRightArrow, true, evnt);
}
}
}
}
}
}
else if (treeConfig && (rowOpts.isCurrent || highlightCurrentRow) && currentRow) {
// 如果是树形表格当前行回车移动到子节点
const childrens = currentRow[childrenField];
if (childrens && childrens.length) {
evnt.preventDefault();
const targetRow = childrens[0];
const params = {
$table: $xeTable,
row: targetRow,
rowIndex: $xeTable.getRowIndex(targetRow),
$rowIndex: $xeTable.getVMRowIndex(targetRow)
};
$xeTable.setTreeExpand(currentRow, true)
.then(() => $xeTable.scrollToRow(targetRow))
.then(() => $xeTable.triggerCurrentRowEvent(evnt, params));
}
}
}
}
else if (operArrow && keyboardConfig && keyboardOpts.isArrow) {
if (!isEditStatus) {
// 如果按下了方向键
if (mouseOpts.selected && selectRow && selectColumn) {
$xeTable.moveArrowSelected(selected.args, isLeftArrow, isUpArrow, isRightArrow, isDwArrow, evnt);
}
else {
// 当前行按键上下移动
if ((isUpArrow || isDwArrow) && (rowOpts.isCurrent || highlightCurrentRow)) {
$xeTable.moveCurrentRow(isUpArrow, isDwArrow, evnt);
}
// 当前行按键左右移动
if ((isLeftArrow || isRightArrow) && (columnOpts.isCurrent || highlightCurrentColumn)) {
$xeTable.moveCurrentColumn(isLeftArrow, isRightArrow, evnt);
}
}
}
}
else if (isTab && keyboardConfig && keyboardOpts.isTab) {
// 如果按下了 Tab 键切换
if (selectRow || actived.row) {
const activeRow = selectRow || actived.row;
const activeColumn = selectColumn || actived.column;
if (activeColumn) {
const activeParams = selectRow ? selected.args : actived.args;
const _rowIndex = $xeTable.getVTRowIndex(activeRow);
const _columnIndex = $xeTable.getVTColumnIndex(activeColumn);
const ttrParams = {
row: activeRow,
rowIndex: $xeTable.getRowIndex(activeRow),
$rowIndex: $xeTable.getVMRowIndex(activeRow),
_rowIndex,
column: activeColumn,
columnIndex: $xeTable.getColumnIndex(activeColumn),
$columnIndex: $xeTable.getVMColumnIndex(activeColumn),
_columnIndex,
$table: $xeTable
};
if (!beforeTabMethod || beforeTabMethod(ttrParams) !== false) {
evnt.preventDefault();
// 最后一行按下Tab键,自动追加一行
if (isLastTabAppendRow) {
const newColumn = visibleColumn[0];
if (_rowIndex >= afterFullData.length - 1 && _columnIndex >= visibleColumn.length - 1) {
if (actived.row) {
$xeTable.handleClearEdit(evnt);
}
$xeTable.insertAt({}, -1).then(({ row: newRow }) => {
$xeTable.scrollToRow(newRow, newColumn);
$xeTable.handleSelected(Object.assign(Object.assign({}, activeParams), { row: newRow, column: newColumn }), evnt);
});
$xeTable.dispatchEvent('tab-append-row', ttrParams, evnt);
return;
}
}
if (tabMethod) {
tabMethod(ttrParams);
}
else {
if (actived.row) {
$xeTable.handleClearEdit(evnt);
}
$xeTable.moveTabSelected(activeParams, hasShiftKey, evnt);
}
}
}
}
}
else if (keyboardConfig && keyboardOpts.isDel && hasDeleteKey && isEnableConf(editConfig) && (selectRow || selectColumn)) {
// 如果是删除键
if (!isEditStatus) {
const { delMethod } = keyboardOpts;
const params = {
row: selectRow,
rowIndex: $xeTable.getRowIndex(selectRow),
column: selectColumn,
columnIndex: $xeTable.getColumnIndex(selectColumn),
$table: $xeTable,
$grid: $xeGrid,
$gantt: $xeGantt
};
// 是否被禁用
if (!beforeEditMethod || beforeEditMethod(params)) {
if (delMethod) {
delMethod(params);
}
else {
const selectCellValue = getCellValue(selectRow, selectColumn);
if (selectCellValue !== null) {
$xeTable.handlePushStack();
setCellValue(selectRow, selectColumn, null);
}
}
// 如果按下 del 键,更新表尾数据
$xeTable.updateFooter();
dispatchEvent('cell-delete-value', params, evnt);
}
}
}
else if (hasBackspaceKey && keyboardConfig && keyboardOpts.isBack && isEnableConf(editConfig) && (selectRow || selectColumn)) {
if (!isEditStatus) {
const { backMethod } = keyboardOpts;
// 如果是删除键
if (keyboardOpts.isDel && isEnableConf(editConfig) && (selectRow || selectColumn)) {
const params = {
row: selectRow,
rowIndex: $xeTable.getRowIndex(selectRow),
$rowIndex: $xeTable.getVMRowIndex(selectRow),
_rowIndex: $xeTable.getVTRowIndex(selectRow),
column: selectColumn,
columnIndex: $xeTable.getColumnIndex(selectColumn),
$columnIndex: $xeTable.getVMColumnIndex(selectColumn),
_columnIndex: $xeTable.getVTColumnIndex(selectColumn),
$table: $xeTable,
$grid: $xeGrid,
$gantt: $xeGantt
};
// 是否被禁用
if (!beforeEditMethod || beforeEditMethod(params)) {
if (backMethod) {
backMethod(params);
}
else {
$xeTable.handleEdit(params, evnt, {
isClear: true
});
}
dispatchEvent('cell-backspace-value', params, evnt);
}
}
}
}
else if (hasBackspaceKey && keyboardConfig && treeConfig && keyboardOpts.isBack && (rowOpts.isCurrent || highlightCurrentRow) && currentRow) {
// 如果树形表格回退键关闭当前行返回父节点
const { parent: parentRow } = XEUtils.findTree(internalData.afterTreeFullData, item => item === currentRow, { children: childrenField });
if (parentRow) {
evnt.preventDefault();
const params = {
row: parentRow,
rowIndex: $xeTable.getRowIndex(parentRow),
$rowIndex: $xeTable.getVMRowIndex(parentRow),
$table: $xeTable,
$grid: $xeGrid,
$gantt: $xeGantt
};
$xeTable.setTreeExpand(parentRow, false)
.then(() => $xeTable.scrollToRow(parentRow))
.then(() => $xeTable.triggerCurrentRowEvent(evnt, params));
}
}
else if (keyboardConfig && keyboardOpts.isUndoRedo && isControlKey && (isZ || isY) && !hasEventInputTarget(evnt.target)) {
if (evnt.target) {
if (isY || (hasShiftKey && isZ)) {
// 恢复被撤销的操作:Ctrl + Y 或 Ctrl + Shift + Z
evnt.preventDefault();
$xeTable.handleRedoStackEvent(evnt);
}
else if (isZ) {
// 撤销上一步操作:Ctrl + Z
evnt.preventDefault();
$xeTable.handleUndoStackEvent(evnt);
}
}
}
else if (keyboardConfig && isEnableConf(editConfig) && keyboardOpts.isEdit && !isControlKey && (isSpacebar || isProcess || evnt.key === 'Process' || (keyCode >= 48 && keyCode <= 57) || (keyCode >= 65 && keyCode <= 90) || (keyCode >= 96 && keyCode <= 111) || (keyCode >= 186 && keyCode <= 192) || (keyCode >= 219 && keyCode <= 222))) {
const { editMode, editMethod } = keyboardOpts;
// 启用编辑后,空格键功能将失效
// if (isSpacebar) {
// evnt.preventDefault()
// }
// 如果是按下非功能键之外允许直接编辑
if (selectColumn && selectRow && isEnableConf(selectColumn.editRender)) {
const beforeEditMethod = editOpts.beforeEditMethod || editOpts.activeMethod;
const params = {
row: selectRow,
rowIndex: $xeTable.getRowIndex(selectRow),
$rowIndex: $xeTable.getVMRowIndex(selectRow),
_rowIndex: $xeTable.getVTRowIndex(selectRow),
column: selectColumn,
columnIndex: $xeTable.getColumnIndex(selectColumn),
$columnIndex: $xeTable.getVMColumnIndex(selectColumn),
_columnIndex: $xeTable.getVTColumnIndex(selectColumn),
$table: $xeTable,
$grid: $xeGrid,
$gantt: $xeGantt
};
if (!beforeEditMethod || beforeEditMethod(params)) {
if (editMethod) {
editMethod(params);
}
else {
let isClearValue = false;
// 追加方式与覆盖式
if (editMode !== 'insert') {
isClearValue = true;
}
$xeTable.handleEdit(params, evnt, {
isClear: isClearValue
});
}
}
}
}
dispatchEvent('keydown', {}, evnt);
});
}
};
const handleGlobalPasteEvent = (evnt) => {
const { keyboardConfig, mouseConfig } = props;
const { editStore, filterStore } = reactData;
const { isActivated } = internalData;
const mouseOpts = computeMouseOpts.value;
const keyboardOpts = computeKeyboardOpts.value;
const { actived } = editStore;
if (isActivated && !filterStore.visible) {
if (!(actived.row || actived.column)) {
if (keyboardConfig && keyboardOpts.isClip && mouseConfig && mouseOpts.area && $xeTable.handlePeClAreaEvent) {
$xeTable.handlePeClAreaEvent(evnt);
}
}
dispatchEvent('paste', {}, evnt);
}
};
const handleGlobalCopyEvent = (evnt) => {
const { keyboardConfig, mouseConfig } = props;
const { editStore, filterStore } = reactData;
const { isActivated } = internalData;
const mouseOpts = computeMouseOpts.value;
const keyboardOpts = computeKeyboardOpts.value;
const { actived } = editStore;
if (isActivated && !filterStore.visible) {
if (!(actived.row || actived.column)) {
if (keyboardConfig && keyboardOpts.isClip && mouseConfig && mouseOpts.area && $xeTable.handleCyClAreaEvent) {
$xeTable.handleCyClAreaEvent(evnt);
}
}
dispatchEvent('copy', {}, evnt);
}
};
const handleGlobalCutEvent = (evnt) => {
const { keyboardConfig, mouseConfig } = props;
const { editStore, filterStore } = reactData;
const { isActivated } = internalData;
const mouseOpts = computeMouseOpts.value;
const keyboardOpts = computeKeyboardOpts.value;
const { actived } = editStore;
if (isActivated && !filterStore.visible) {
if (!(actived.row || actived.column)) {
if (keyboardConfig && keyboardOpts.isClip && mouseConfig && mouseOpts.area && $xeTable.handleCutCellAreaEvent) {
$xeTable.handleCutCellAreaEvent(evnt);
}
}
dispatchEvent('cut', {}, evnt);
}
};
const handleGlobalResizeEvent = () => {
if ($xeTable.closeMenu) {
$xeTable.closeMenu();
}
const el = refElem.value;
if (!el || !el.clientWidth) {
return;
}
if (internalData.rsePending) {
return;
}
handleResizeEvent();
};
const handleTargetEnterEvent = (isClear) => {
const $tooltip = refTooltip.value;
clearTimeout(internalData.tooltipTimeout);
if (isClear) {
$xeTable.closeTooltip();
}
else {
if ($tooltip && $tooltip.setActived) {
$tooltip.setActived(true);
}
}
};
const clearCrossTableDragStatus = () => {
crossTableDragRowObj = null;
crossTableDragRowInfo.row = null;
};
const clearDragStatus = () => {
const { dragRow, dragCol } = reactData;
if (dragRow || dragCol) {
clearColDropOrigin();
clearRowDropOrigin();
hideDropTip();
clearCrossTableDragStatus();
reactData.dragRow = null;
reactData.dragCol = null;
}
};
const handleRowDragEndClearStatus = () => {
clearRowDragData();
clearCrossTableDragStatus();
handleRecalculateStyle(false, true, true);
};
const handleColDragEndClearStatus = () => {
clearColDragData();
clearCrossTableDragStatus();
handleRecalculateStyle(true, true, true);
};
const clearRowDropOrigin = () => {
const el = refElem.value;
if (el) {
const clss = 'row--drag-origin';
XEUtils.arrayEach(el.querySelectorAll(`.${clss}`), (elem) => {
elem.draggable = false;
removeClass(elem, clss);
});
}
};
const updateRowDropOrigin = (row) => {
const el = refElem.value;
if (el) {
const clss = 'row--drag-origin';
const rowid = getRowid($xeTable, row);
XEUtils.arrayEach(el.querySelectorAll(`[rowid="${rowid}"]`), (elem) => {
addClass(elem, clss);
});
}
};
const updateRowDropTipContent = (tdEl) => {
const { dragConfig } = props;
const { dragRow } = reactData;
const rowDragOpts = computeRowDragOpts.value;
const { tooltipMethod } = rowDragOpts;
const rTooltipMethod = tooltipMethod || (dragConfig ? dragConfig.rowTooltipMethod : null);
let tipContent = '';
if (rTooltipMethod) {
const rtParams = {
$table: $xeTable,
row: dragRow
};
tipContent = `${rTooltipMethod(rtParams) || ''}`;
}
else {
tipContent = getI18n('vxe.table.dragTip', [tdEl.textContent || '']);
}
reactData.dragTipText = tipContent;
};
const updateColDropOrigin = (column) => {
const el = refElem.value;
if (el) {
const colQuerys = [];
XEUtils.eachTree([column], item => {
colQuerys.push(`[colid="${item.id}"]`);
});
const clss = 'col--drag-origin';
XEUtils.arrayEach(el.querySelectorAll(colQuerys.join(',')), (elem) => {
addClass(elem, clss);
});
}
};
const clearColDropOrigin = () => {
const el = refElem.value;
if (el) {
const clss = 'col--drag-origin';
XEUtils.arrayEach(el.querySelectorAll(`.${clss}`), (elem) => {
elem.draggable = false;
removeClass(elem, clss);
});
}
};
const updateColDropTipContent = (tdEl) => {
const { dragCol } = reactData;
const columnDragOpts = computeColumnDragOpts.value;
const { tooltipMethod } = columnDragOpts;
let tipContent = '';
if (tooltipMethod) {
const dtParams = {
$table: $xeTable,
column: dragCol
};
tipContent = `${tooltipMethod(dtParams) || ''}`;
}
else {
tipContent = getI18n('vxe.table.dragTip', [tdEl.textContent || '']);
}
reactData.dragTipText = tipContent;
};
const showDropTip = (evnt, trEl, thEl, showLine, dragPos) => {
let wrapperEl = refElem.value;
if ($xeGantt && trEl) {
const { refGanttContainerElem } = $xeGantt.getRefMaps();
const ganttContainerElem = refGanttContainerElem.value;
if (ganttContainerElem) {
wrapperEl = ganttContainerElem;
}
}
if (!wrapperEl) {
return;
}
const { overflowX, scrollbarWidth, overflowY, scrollbarHeight } = reactData;
const { prevDragToChild } = internalData;
const wrapperRect = wrapperEl.getBoundingClientRect();
const osbWidth = overflowY ? scrollbarWidth : 0;
const osbHeight = overflowX ? scrollbarHeight : 0;
const tableWrapperWidth = wrapperEl.clientWidth;
const tableWrapperHeight = wrapperEl.clientHeight;
if (trEl) {
const rdLineEl = refDragRowLineElem.value;
if (rdLineEl) {
if (showLine) {
const scrollbarYToLeft = computeScrollbarYToLeft.value;
const trRect = trEl.getBoundingClientRect();
let trHeight = trEl.clientHeight;
const offsetTop = Math.max(1, trRect.y - wrapperRect.y);
if (offsetTop + trHeight > tableWrapperHeight - osbHeight) {
trHeight = tableWrapperHeight - offsetTop - osbHeight;
}
rdLineEl.style.display = 'block';
rdLineEl.style.left = `${scrollbarYToLeft ? osbWidth : 0}px`;
rdLineEl.style.top = `${offsetTop}px`;
rdLineEl.style.height = `${trHeight}px`;
rdLineEl.style.width = `${tableWrapperWidth - osbWidth}px`;
rdLineEl.setAttribute('drag-pos', dragPos);
rdLineEl.setAttribute('drag-to-child', prevDragToChild ? 'y' : 'n');
}
else {
rdLineEl.style.display = '';
}
}
}
else if (thEl) {
const cdLineEl = refDragColLineElem.value;
if (cdLineEl) {
if (showLine) {
const scrollbarXToTop = computeScrollbarXToTop.value;
const leftContainerElem = refLeftContainer.value;
const leftContainerWidth = leftContainerElem ? leftContainerElem.clientWidth : 0;
const rightContainerElem = refRightContainer.value;
const rightContainerWidth = rightContainerElem ? rightContainerElem.clientWidth : 0;
const thRect = thEl.getBoundingClientRect();
let thWidth = thEl.clientWidth;
const offsetTop = Math.max(0, thRect.y - wrapperRect.y);
const startX = leftContainerWidth;
let offsetLeft = thRect.x - wrapperRect.x;
if (offsetLeft < startX) {
thWidth -= startX - offsetLeft;
offsetLeft = startX;
}
const endX = tableWrapperWidth - rightContainerWidth - (rightContainerWidth ? 0 : osbWidth);
if (offsetLeft + thWidth > endX) {
thWidth = endX - offsetLeft;
}
cdLineEl.style.display = 'block';
cdLineEl.style.top = `${offsetTop}px`;
cdLineEl.style.left = `${offsetLeft}px`;
cdLineEl.style.width = `${thWidth}px`;
if (prevDragToChild) {
cdLineEl.style.height = `${thRect.height}px`;
}
else {
cdLineEl.style.height = `${tableWrapperHeight - offsetTop - (scrollbarXToTop ? 0 : osbHeight)}px`;
}
cdLineEl.setAttribute('drag-pos', dragPos);
cdLineEl.setAttribute('drag-to-child', prevDragToChild ? 'y' : 'n');
}
else {
cdLineEl.style.display = '';
}
}
}
const rdTipEl = refDragTipElem.value;
if (rdTipEl) {
rdTipEl.style.display = 'block';
rdTipEl.style.top = `${Math.min(wrapperEl.clientHeight - wrapperEl.scrollTop - rdTipEl.clientHeight, evnt.clientY - wrapperRect.y)}px`;
rdTipEl.style.left = `${Math.min(wrapperEl.clientWidth - wrapperEl.scrollLeft - rdTipEl.clientWidth - 16, evnt.clientX - wrapperRect.x)}px`;
rdTipEl.setAttribute('drag-status', showLine ? (prevDragToChild ? 'sub' : 'normal') : 'disabled');
}
};
const hideDropTip = () => {
const rdTipEl = refDragTipElem.value;
const rdLineEl = refDragRowLineElem.value;
const cdLineEl = refDragColLineElem.value;
if (rdTipEl) {
rdTipEl.style.display = '';
}
if (rdLineEl) {
rdLineEl.style.display = '';
}
if (cdLineEl) {
cdLineEl.style.display = '';
}
};
const clearRowDragData = () => {
let wrapperEl = refElem.value;
const dtClss = ['.vxe-body--row'];
if ($xeGantt) {
const { refGanttContainerElem } = $xeGantt.getRefMaps();
const ganttContainerElem = refGanttContainerElem.value;
if (ganttContainerElem) {
wrapperEl = ganttContainerElem;
}
dtClss.push('.vxe-gantt-view--body-row', '.vxe-gantt-view--chart-row');
}
hideDropTip();
clearRowDropOrigin();
clearRowAnimate(wrapperEl, dtClss);
internalData.prevDragToChild = false;
reactData.dragRow = null;
reactData.dragCol = null;
};
const clearColDragData = () => {
const el = refElem.value;
hideDropTip();
clearColDropOrigin();
clearColAnimate(el, ['.vxe-table--column']);
internalData.prevDragToChild = false;
reactData.dragRow = null;
reactData.dragCol = null;
};
/**
* 处理显示 tooltip
* @param {Event} evnt 事件
* @param {Row} row 行对象
*/
const handleTooltip = (evnt, tipOpts, type, tdEl, overflowElem, tipElem, params) => {
const tipOverEl = overflowElem || tdEl;
if (!tipOverEl) {
return nextTick();
}
params.cell = tdEl;
const { tooltipStore } = reactData;
const { column, row } = params;
const { showAll, contentMethod } = tipOpts;
const cellText = XEUtils.toString(column.type === 'html' ? tipOverEl.innerText : tipOverEl.textContent).trim();
const isOver = tipOverEl.scrollWidth > tipOverEl.clientWidth;
let isShow = false;
let customContent = null;
let content = '';
if (contentMethod) {
customContent = contentMethod(params);
}
// 是否全部展示
if (showAll) {
// 如果为 null 默认显示
if (XEUtils.eqNull(customContent)) {
isShow = true;
content = cellText;
}
else if (customContent !== '' && customContent !== false) {
// 如果为 '' | false 则不显示
isShow = true;
content = '' + customContent;
}
}
else {
// 如果为 null 使用默认逻辑
if (XEUtils.eqNull(customContent)) {
isShow = isOver;
content = cellText;
}
else if (customContent !== '' && customContent !== false) {
// 如果为 '' | false 则不显示
isShow = true;
content = customContent;
}
else {
content = cellText;
}
}
if (isShow && content) {
const tipContent = formatText(content);
Object.assign(tooltipStore, {
row,
column,
visible: true,
content: tipContent,
type,
currOpts: tipOpts
});
nextTick(() => {
const $tooltip = refTooltip.value;
if ($tooltip && $tooltip.open) {
$tooltip.open(isOver ? tipOverEl : tipElem, tipContent);
}
});
}
return nextTick();
};
const truncateStackHistory = () => {
const { stackHistoryStore } = internalData;
const { undoStacks } = stackHistoryStore;
const undoRedoHistoryOpts = computeUndoRedoHistoryOpts.value;
const { stackSize } = undoRedoHistoryOpts;
if (undoStacks.length > XEUtils.toNumber(stackSize)) {
undoStacks.shift();
}
};
/**
* 生成快照数据
*/
const getSnapshotStackData = () => {
const { editStore } = reactData;
const { afterFullData, elemStore, insertRowMaps, removeRowMaps } = internalData;
const { selected, actived } = editStore;
const { row: selectRow, column: selectColumn } = selected;
const { row: editRow, column: editColumn } = actived;
const bodyScrollElem = getRefElem(elemStore['main-body-scroll']);
const stackObj = {
selectActiveInfo: selectRow && selectColumn
? {
rowid: getRowid($xeTable, selectRow),
colid: selectColumn.id
}
: undefined,
editActiveInfo: editRow && editColumn
? {
rowid: getRowid($xeTable, editRow),
colid: editColumn.id
}
: undefined,
scrollInfo: {
top: bodyScrollElem ? bodyScrollElem.scrollTop : 0,
left: bodyScrollElem ? bodyScrollElem.scrollLeft : 0
},
insertData: XEUtils.clone(XEUtils.values(insertRowMaps), true),
removeData: XEUtils.clone(XEUtils.values(removeRowMaps), true),
visibleData: XEUtils.clone(afterFullData, true),
visibleTreeData: [],
visibleColumn: []
};
return $xeTable.getCellAreaPushStackObj ? $xeTable.getCellAreaPushStackObj(stackObj) : stackObj;
};
/**
* 刷新栈视图
*/
const handleUpdateSnapshotStackData = (stackObj) => {
const { treeConfig } = props;
const { editStore } = reactData;
const { fullAllDataRowIdData, fullColumnIdData } = internalData;
if (!stackObj) {
return;
}
const treeOpts = computeTreeOpts.value;
const { transform } = treeOpts;
const { visibleData, editActiveInfo, selectActiveInfo, scrollInfo, insertData, removeData } = stackObj;
const iRowMaps = {};
insertData.forEach(item => {
const rowid = getRowid($xeTable, item);
const rest = fullAllDataRowIdData[rowid];
let row = item;
if (rest) {
row = rest.row;
Object.assign(row, item);
}
iRowMaps[rowid] = row;
});
const rRowMaps = {};
removeData.forEach(item => {
const rowid = getRowid($xeTable, item);
const rest = fullAllDataRowIdData[rowid];
let row = item;
if (rest) {
row = rest.row;
Object.assign(row, item);
}
rRowMaps[rowid] = row;
});
const afterFullList = visibleData.map(item => {
const rowid = getRowid($xeTable, item);
const rest = fullAllDataRowIdData[rowid];
let row = item;
if (rest) {
row = rest.row;
Object.assign(row, item);
}
return row;
});
internalData.insertRowMaps = iRowMaps;
internalData.removeRowMaps = rRowMaps;
internalData.afterFullData = afterFullList;
$xeTable.cacheRowMap(false);
$xeTable.handleTableData(treeConfig && transform);
$xeTable.updateFooter();
$xeTable.handleUpdateBodyMerge();
if (!(treeConfig && transform)) {
$xeTable.updateAfterDataIndex();
}
$xeTable.checkSelectionStatus();
if (reactData.scrollYLoad) {
$xeTable.updateScrollYSpace();
}
if ($xeTable.handleCellAreaSnapshotStackData) {
$xeTable.handleCellAreaSnapshotStackData(stackObj);
}
else {
const { selected } = editStore;
const mouseOpts = computeMouseOpts.value;
let selectRowid = '';
let selectColid = '';
if (editActiveInfo) {
selectRowid = editActiveInfo.rowid;
selectColid = editActiveInfo.colid;
}
else if (selectActiveInfo) {
selectRowid = selectActiveInfo.rowid;
selectColid = selectActiveInfo.colid;
}
if (selectRowid && selectColid && mouseOpts.selected) {
const editRow = fullAllDataRowIdData[selectRowid] ? fullAllDataRowIdData[selectRowid].row : null;
const editColumn = fullColumnIdData[selectColid] ? fullColumnIdData[selectColid].column : null;
if (editRow && editColumn) {
const params = {
row: editRow,
column: editColumn
};
selected.row = editRow;
selected.column = editColumn;
selected.args = params;
nextTick(() => {
$xeTable.addCellSelectedClass();
$xeTable.scrollTo(scrollInfo);
});
}
}
}
};
const callSlot = (slotFunc, params) => {
if (slotFunc) {
if ($xeGGWrapper) {
return $xeGGWrapper.callSlot(slotFunc, params);
}
// if (XEUtils.isString(slotFunc)) {
// slotFunc = slots[slotFunc] || null
// }
if (XEUtils.isFunction(slotFunc)) {
return getSlotVNs(slotFunc(params));
}
}
return [];
};
/**
* 内部方法
*/
tablePrivateMethods = {
getSetupOptions() {
return getConfig();
},
updateAfterDataIndex,
callSlot,
/**
* 获取父容器元素
*/
getParentElem() {
const el = refElem.value;
if ($xeGGWrapper) {
const gridEl = $xeGGWrapper.getRefMaps().refElem.value;
return gridEl ? gridEl.parentNode : null;
}
return el ? el.parentNode : null;
},
/**
* 获取父容器的高度
*/
getParentHeight() {
const { height } = props;
const el = refElem.value;
if (el) {
const parentElem = el.parentNode;
let parentPaddingSize = 0;
let parentWrapperHeight = 0;
if (parentElem) {
if ($xeGantt && hasClass(parentElem, 'vxe-gantt--table-wrapper')) {
parentWrapperHeight = $xeGantt.getParentHeight();
}
else if ($xeGrid && hasClass(parentElem, 'vxe-grid--table-wrapper')) {
parentWrapperHeight = $xeGrid.getParentHeight();
}
else {
parentWrapperHeight = parentElem.clientHeight;
parentPaddingSize = height === '100%' || height === 'auto' ? getPaddingTopBottomSize(parentElem) : 0;
}
}
return Math.floor(parentWrapperHeight - parentPaddingSize);
}
return 0;
},
/**
* 获取需要排除的高度
* 但渲染表格高度时,需要排除工具栏或分页等相关组件的高度
* 如果存在表尾合计滚动条,则需要排除滚动条高度
*/
getExcludeHeight() {
return $xeGGWrapper ? $xeGGWrapper.getExcludeHeight() : 0;
},
/**
* 定义行数据中的列属性,如果不存在则定义
* @param {Row} records 行数据
*/
defineField(records) {
const { treeConfig } = props;
const expandOpts = computeExpandOpts.value;
const treeOpts = computeTreeOpts.value;
const radioOpts = computeRadioOpts.value;
const rowOpts = computeRowOpts.value;
const checkboxOpts = computeCheckboxOpts.value;
const childrenField = treeOpts.children || treeOpts.childrenField;
const rowkey = getRowkey($xeTable);
if (!XEUtils.isArray(records)) {
records = [records];
}
return records.map(record => {
internalData.tableFullColumn.forEach(column => {
const { field, editRender } = column;
if (field && !XEUtils.has(record, field) && !record[field]) {
let cellValue = null;
if (editRender) {
const { defaultValue } = editRender;
if (XEUtils.isFunction(defaultValue)) {
cellValue = defaultValue({ column });
}
else if (!XEUtils.isUndefined(defaultValue)) {
cellValue = defaultValue;
}
}
XEUtils.set(record, field, cellValue);
}
});
const otherFields = [radioOpts.labelField, checkboxOpts.checkField, checkboxOpts.labelField, expandOpts.labelField];
otherFields.forEach((key) => {
if (key && eqEmptyValue(XEUtils.get(record, key))) {
XEUtils.set(record, key, null);
}
});
if (treeConfig && treeOpts.lazy && XEUtils.isUndefined(record[childrenField])) {
record[childrenField] = null;
}
// 必须有行数据的唯一主键,可以自行设置;也可以默认生成一个随机数
if (eqEmptyValue(XEUtils.get(record, rowkey))) {
XEUtils.set(record, rowkey, createRowId(rowOpts, record, rowkey));
}
return record;
});
},
handleTableData(force) {
const { scrollYLoad } = reactData;
const { scrollYStore, fullDataRowIdData } = internalData;
const $xeGanttView = internalData.xeGanttView;
let fullList = internalData.afterFullData;
// 是否进行数据处理
if (force) {
// 更新数据,处理筛选和排序
updateAfterFullData();
// 如果为虚拟树,将树结构拍平
fullList = handleVirtualTreeToList();
// 更新数据后清除合并缓存,涉及分组、筛选、排序等
internalData.mergeHeaderRowMaps = {};
internalData.mergeHeaderColMaps = {};
internalData.mergeBodyRowMaps = {};
internalData.mergeBodyColMaps = {};
internalData.mergeFooterRowMaps = {};
internalData.mergeFooterColMaps = {};
}
const tableData = scrollYLoad ? fullList.slice(scrollYStore.startIndex, scrollYStore.endIndex) : fullList.slice(0);
const visibleDataRowIdMaps = {};
tableData.forEach((row, $index) => {
const rowid = getRowid($xeTable, row);
const rest = fullDataRowIdData[rowid];
if (rest) {
rest.$index = $index;
}
visibleDataRowIdMaps[rowid] = row;
});
reactData.tableData = tableData;
internalData.visibleDataRowIdData = visibleDataRowIdMaps;
if ($xeGanttView && $xeGanttView.updateViewData) {
$xeGanttView.updateViewData(force);
}
return nextTick();
},
/**
* 更新数据行的 Map
*/
cacheRowMap(isReset) {
const { treeConfig } = props;
const { isRowGroupStatus } = reactData;
const { currKeyField, fullAllDataRowIdData, tableFullData, tableFullTreeData, tableFullGroupData, treeExpandedMaps, rowExpandedMaps, selectCheckboxMaps } = internalData;
const fullAllDataRowIdMaps = isReset ? {} : Object.assign({}, fullAllDataRowIdData); // 存在已删除数据
const fullDataRowIdMaps = {};
const idMaps = {};
const { handleUpdateRowId } = createHandleUpdateRowId($xeTable);
let rowNum = 0;
const handleRowCache = (row, index, items, currIndex, parentRow, rowid, level, seq) => {
let rowRest = fullAllDataRowIdMaps[rowid];
if (idMaps[rowid]) {
errLog('vxe.error.repeatKey', [currKeyField, rowid]);
}
if (!rowRest) {
rowRest = { row, rowid, _seq: -1, seq, index: -1, _index: -1, $index: -1, treeIndex: index, _tIndex: -1, items, parent: parentRow, level, height: 0, resizeHeight: 0, oTop: 0, expandHeight: 0 };
fullDataRowIdMaps[rowid] = rowRest;
fullAllDataRowIdMaps[rowid] = rowRest;
}
rowRest.treeLoaded = false;
rowRest.expandLoaded = false;
rowRest._seq = rowNum++;
rowRest.row = row;
rowRest.items = items;
rowRest.parent = parentRow;
rowRest.level = level;
rowRest.index = currIndex;
rowRest.treeIndex = index;
// 更新缓存
if (selectCheckboxMaps[rowid]) {
selectCheckboxMaps[rowid] = row;
}
if (rowExpandedMaps[rowid]) {
rowExpandedMaps[rowid] = row;
}
rowNum++;
idMaps[rowid] = true;
fullDataRowIdMaps[rowid] = rowRest;
fullAllDataRowIdMaps[rowid] = rowRest;
};
if (treeConfig) {
const treeOpts = computeTreeOpts.value;
const { lazy } = treeOpts;
const childrenField = treeOpts.children || treeOpts.childrenField;
const hasChildField = treeOpts.hasChild || treeOpts.hasChildField;
XEUtils.eachTree(tableFullTreeData, (row, index, items, path, parentRow, nodes) => {
const rowid = handleUpdateRowId(row);
if (lazy) {
if (row[hasChildField] && row[childrenField] === undefined) {
row[childrenField] = null;
}
if (treeExpandedMaps[rowid]) {
if (!row[childrenField] || !row[childrenField].length) {
delete treeExpandedMaps[rowid];
}
}
}
handleRowCache(row, index, items, parentRow ? -1 : index, parentRow, rowid, nodes.length - 1, toTreePathSeq(path));
}, { children: childrenField });
}
else if (isRowGroupStatus) {
const aggregateOpts = computeAggregateOpts.value;
const { mapChildrenField } = aggregateOpts;
XEUtils.eachTree(tableFullGroupData, (row, index, items, path, parentRow, nodes) => {
const rowid = handleUpdateRowId(row);
handleRowCache(row, index, items, parentRow ? -1 : index, parentRow, rowid, nodes.length - 1, toTreePathSeq(path));
}, { children: mapChildrenField });
}
else {
tableFullData.forEach((row, index, items) => {
handleRowCache(row, index, items, index, null, handleUpdateRowId(row), 0, index + 1);
});
}
internalData.fullDataRowIdData = fullDataRowIdMaps;
internalData.fullAllDataRowIdData = fullAllDataRowIdMaps;
reactData.treeExpandedFlag++;
},
cacheSourceMap(fullData) {
const { treeConfig } = props;
const treeOpts = computeTreeOpts.value;
const sourceData = XEUtils.clone(fullData, true);
const { handleUpdateRowId } = createHandleUpdateRowId($xeTable);
const sourceRowIdData = {};
const handleSourceRow = (row) => {
const rowid = handleUpdateRowId(row);
sourceRowIdData[rowid] = row;
};
// 源数据缓存
if (treeConfig) {
const childrenField = treeOpts.children || treeOpts.childrenField;
XEUtils.eachTree(sourceData, handleSourceRow, { children: treeOpts.transform ? treeOpts.mapChildrenField : childrenField });
}
else {
sourceData.forEach(handleSourceRow);
}
internalData.sourceDataRowIdData = sourceRowIdData;
internalData.tableSourceData = sourceData;
},
/**
* 指定列宽的列进行拆分
*/
analyColumnWidth() {
const { tableFullColumn } = internalData;
const columnOpts = computeColumnOpts.value;
const { width: defaultWidth, minWidth: defaultMinWidth } = columnOpts;
const resizeList = [];
const pxList = [];
const pxMinList = [];
const autoMinList = [];
const scaleList = [];
const scaleMinList = [];
const autoList = [];
const remainList = [];
tableFullColumn.forEach((column) => {
if (defaultWidth && !column.width) {
column.width = defaultWidth;
}
if (defaultMinWidth && !column.minWidth) {
column.minWidth = defaultMinWidth;
}
if (column.visible) {
if (column.resizeWidth) {
resizeList.push(column);
}
else if (column.width === 'auto') {
autoList.push(column);
}
else if (isPx(column.width)) {
pxList.push(column);
}
else if (isScale(column.width)) {
scaleList.push(column);
}
else if (isPx(column.minWidth)) {
pxMinList.push(column);
}
else if (column.minWidth === 'auto') {
autoMinList.push(column);
}
else if (isScale(column.minWidth)) {
scaleMinList.push(column);
}
else {
remainList.push(column);
}
}
});
Object.assign(reactData.columnStore, { resizeList, pxList, pxMinList, autoMinList, scaleList, scaleMinList, autoList, remainList });
},
handleColResizeMousedownEvent(evnt, fixedType, params) {
const isLeftBtn = evnt.button === 0;
if (!isLeftBtn) {
return;
}
evnt.stopPropagation();
evnt.preventDefault();
const { column } = params;
const { columnStore, overflowX, scrollbarHeight } = reactData;
const { visibleColumn } = internalData;
const { leftList, rightList } = columnStore;
const resizableOpts = computeResizableOpts.value;
const osbHeight = overflowX ? scrollbarHeight : 0;
const tableEl = refElem.value;
const leftContainerElem = refLeftContainer.value;
const rightContainerElem = refRightContainer.value;
const resizeBarElem = refColResizeBar.value;
if (!resizeBarElem) {
return;
}
const isLeftFixed = fixedType === 'left';
const isRightFixed = fixedType === 'right';
const resizeTipElem = resizeBarElem.firstElementChild;
const scrollbarXToTop = computeScrollbarXToTop.value;
const { clientX: dragClientX } = evnt;
const dragBtnElem = evnt.target;
let cell = dragBtnElem.parentElement;
let resizeColumn = column;
const isDragGroupCol = column.children && column.children.length;
if (isDragGroupCol) {
resizeColumn = getLastChildColumn(column);
if (isDragGroupCol) {
const trEl = cell ? cell.parentElement : null;
const theadEl = trEl ? trEl.parentElement : null;
cell = theadEl ? theadEl.querySelector(`.vxe-header--column[colid="${resizeColumn.id}"]`) : null;
}
}
if (!cell) {
return;
}
const cellParams = XEUtils.assign(params, { cell, $table: $xeTable });
let dragLeft = 0;
const tableRect = tableEl.getBoundingClientRect();
const rightContainerRect = rightContainerElem ? rightContainerElem.getBoundingClientRect() : null;
const cellRect = cell.getBoundingClientRect();
const dragBtnRect = dragBtnElem.getBoundingClientRect();
const dragBtnWidth = dragBtnElem.clientWidth;
const dragBtnOffsetWidth = XEUtils.floor(dragBtnWidth / 2);
const dragPosLeft = dragBtnRect.x - tableRect.x + dragBtnOffsetWidth;
const minInterval = getColReMinWidth(cellParams) - dragBtnOffsetWidth; // 列之间的最小间距
const maxInterval = getColReMaxWidth(cellParams); // 列之间的最大间距
const dragMinLeft = isRightFixed ? 0 : (cellRect.x - tableRect.x + dragBtnWidth + minInterval);
const dragMaxLeft = cellRect.x - tableRect.x + cell.clientWidth - minInterval;
let fixedLeftRemainWidth = 0;
let fixedRightRemainWidth = 0;
if (isLeftFixed || isRightFixed) {
let isMach = false;
const fixedColumn = isLeftFixed ? leftList : rightList;
for (let i = 0; i < fixedColumn.length; i++) {
const item = fixedColumn[i];
if (isMach) {
fixedLeftRemainWidth += item.renderWidth;
}
else {
isMach = item.id === resizeColumn.id;
if (!isMach) {
fixedRightRemainWidth += item.renderWidth;
}
}
}
}
// 处理拖动事件
const updateEvent = (evnt) => {
evnt.stopPropagation();
evnt.preventDefault();
const tableHeight = tableEl.clientHeight;
const offsetX = evnt.clientX - dragClientX;
let left = dragPosLeft + offsetX;
if (isLeftFixed) {
if (rightContainerRect) {
left = Math.min(left, rightContainerRect.x - tableRect.x - fixedLeftRemainWidth - minInterval);
}
}
else if (isRightFixed) {
if (leftContainerElem) {
left = Math.max(left, leftContainerElem.clientWidth + fixedRightRemainWidth + minInterval);
}
left = Math.min(left, dragMaxLeft);
}
dragLeft = Math.max(left, dragMinLeft);
// 最大宽
if (maxInterval > 1) {
dragLeft = Math.min(dragLeft, maxInterval + dragMinLeft - minInterval);
}
const resizeBarLeft = Math.max(1, dragLeft);
resizeBarElem.style.left = `${resizeBarLeft}px`;
resizeBarElem.style.top = `${scrollbarXToTop ? osbHeight : 0}px`;
resizeBarElem.style.height = `${scrollbarXToTop ? tableHeight - osbHeight : tableHeight}px`;
if (resizableOpts.showDragTip && resizeTipElem) {
resizeTipElem.textContent = getI18n('vxe.table.resizeColTip', [Math.floor(resizeColumn.renderWidth + (isRightFixed ? dragPosLeft - dragLeft : dragLeft - dragPosLeft))]);
const tableWrapperWidth = tableEl.clientWidth;
const resizeBarWidth = resizeBarElem.clientWidth;
const resizeTipWidth = resizeTipElem.clientWidth;
const resizeTipHeight = resizeTipElem.clientHeight;
let resizeTipLeft = -resizeTipWidth;
if (resizeBarLeft < resizeTipWidth + resizeBarWidth) {
resizeTipLeft = 0;
}
else if (resizeBarLeft > tableWrapperWidth) {
resizeTipLeft += tableWrapperWidth - resizeBarLeft;
}
resizeTipElem.style.left = `${resizeTipLeft}px`;
resizeTipElem.style.top = `${Math.min(tableHeight - resizeTipHeight, Math.max(0, evnt.clientY - tableRect.y - resizeTipHeight / 2))}px`;
}
reactData.isDragResize = true;
};
reactData.isDragResize = true;
addClass(tableEl, 'col-drag--resize');
resizeBarElem.style.display = 'block';
document.onmousemove = updateEvent;
document.onmouseup = function (evnt) {
document.onmousemove = null;
document.onmouseup = null;
resizeBarElem.style.display = 'none';
internalData._lastResizeTime = Date.now();
setTimeout(() => {
reactData.isDragResize = false;
}, 50);
const resizeWidth = resizeColumn.renderWidth + (isRightFixed ? dragPosLeft - dragLeft : dragLeft - dragPosLeft);
const resizeParams = Object.assign(Object.assign({}, params), { resizeWidth, resizeColumn });
if (resizableOpts.dragMode === 'fixed') {
visibleColumn.forEach(item => {
if (item.id !== resizeColumn.id) {
if (!item.resizeWidth) {
item.resizeWidth = item.renderWidth;
}
}
});
}
if ($xeTable.handleColResizeCellAreaEvent) {
$xeTable.handleColResizeCellAreaEvent(evnt, resizeParams);
}
else {
resizeColumn.resizeWidth = resizeWidth;
handleUpdateColResize(evnt, resizeParams);
}
removeClass(tableEl, 'col-drag--resize');
};
updateEvent(evnt);
if ($xeTable.closeMenu) {
$xeTable.closeMenu();
}
},
handleColResizeDblclickEvent(evnt, params) {
const resizableOpts = computeResizableOpts.value;
const { isDblclickAutoWidth } = resizableOpts;
const el = refElem.value;
if (isDblclickAutoWidth && el) {
evnt.stopPropagation();
evnt.preventDefault();
const { fullColumnIdData } = internalData;
const { column } = params;
let resizeColumn = column;
if (column.children && column.children.length) {
XEUtils.eachTree(column.children, childColumn => {
resizeColumn = childColumn;
});
}
const colid = resizeColumn.id;
const colRest = fullColumnIdData[colid];
const dragBtnElem = evnt.target;
const cell = dragBtnElem.parentNode;
const cellParams = Object.assign(params, { cell, $table: $xeTable });
const colMinWidth = getColReMinWidth(cellParams);
const colMaxWidth = getColReMaxWidth(cellParams);
el.setAttribute('data-calc-col', 'Y');
let resizeWidth = calcColumnAutoWidth(resizeColumn, el);
el.removeAttribute('data-calc-col');
if (colRest) {
resizeWidth = Math.max(resizeWidth, colRest.width);
}
resizeWidth = Math.max(colMinWidth, resizeWidth);
if (colMaxWidth > 1) {
resizeWidth = Math.min(colMaxWidth, resizeWidth);
}
const resizeParams = Object.assign(Object.assign({}, params), { resizeWidth, resizeColumn });
reactData.isDragResize = false;
internalData._lastResizeTime = Date.now();
if ($xeTable.handleColResizeDblclickCellAreaEvent) {
$xeTable.handleColResizeDblclickCellAreaEvent(evnt, resizeParams);
}
else {
resizeColumn.resizeWidth = resizeWidth;
handleUpdateColResize(evnt, resizeParams);
}
}
},
/**
* @private
*/
handleRowResizeMousedownEvent(evnt, params) {
evnt.stopPropagation();
evnt.preventDefault();
const { row } = params;
const { showOverflow } = props;
const { overflowX, scrollbarWidth, overflowY, scrollbarHeight } = reactData;
const { elemStore, fullAllDataRowIdData } = internalData;
const osbWidth = overflowY ? scrollbarWidth : 0;
const osbHeight = overflowX ? scrollbarHeight : 0;
const scrollbarYToLeft = computeScrollbarYToLeft.value;
const resizableOpts = computeResizableOpts.value;
const rowOpts = computeRowOpts.value;
const cellOpts = computeCellOpts.value;
let tableEl = refElem.value;
if ($xeGantt) {
const { refGanttContainerElem } = $xeGantt.getRefMaps();
const ganttContainerElem = refGanttContainerElem.value;
if (ganttContainerElem) {
tableEl = ganttContainerElem;
}
}
const resizeBarElem = refRowResizeBar.value;
if (!resizeBarElem) {
return;
}
const { clientY: dragClientY } = evnt;
const resizeTipElem = resizeBarElem.firstElementChild;
const dragBtnElem = evnt.currentTarget;
const tdEl = dragBtnElem.parentNode;
const trEl = tdEl.parentNode;
const bodyScrollElem = getRefElem(elemStore['main-body-scroll']);
if (!bodyScrollElem) {
return;
}
const rowid = getRowid($xeTable, row);
const rowRest = fullAllDataRowIdData[rowid];
if (!rowRest) {
return;
}
const defaultRowHeight = computeDefaultRowHeight.value;
let currCellHeight = getCellRestHeight(rowRest, cellOpts, rowOpts, defaultRowHeight);
if (!showOverflow) {
currCellHeight = tdEl.clientHeight;
}
const tableRect = tableEl.getBoundingClientRect();
const trRect = trEl.getBoundingClientRect();
const targetOffsetY = dragClientY - trRect.y - trEl.clientHeight;
let resizeHeight = currCellHeight;
const cellEl = tdEl.querySelector('.vxe-cell');
let cellMinHeight = 0;
if (cellEl) {
const cellStyle = getComputedStyle(cellEl);
cellMinHeight = Math.max(1, Math.ceil(XEUtils.toNumber(cellStyle.paddingTop) + XEUtils.toNumber(cellStyle.paddingBottom)));
}
const minTop = trRect.y - tableRect.y + cellMinHeight;
// 处理拖动事件
const updateEvent = (evnt) => {
evnt.stopPropagation();
evnt.preventDefault();
const rtWidth = tableEl.clientWidth - osbWidth;
const tableHeight = tableEl.clientHeight - osbHeight;
let dragTop = evnt.clientY - tableRect.y - targetOffsetY;
if (dragTop < minTop) {
dragTop = minTop;
}
else {
resizeHeight = Math.max(cellMinHeight, currCellHeight + evnt.clientY - dragClientY);
}
resizeBarElem.style.left = `${scrollbarYToLeft ? osbWidth : 0}px`;
resizeBarElem.style.top = `${dragTop}px`;
resizeBarElem.style.width = `${rtWidth}px`;
if (resizableOpts.showDragTip && resizeTipElem) {
resizeTipElem.textContent = getI18n('vxe.table.resizeRowTip', [resizeHeight]);
const resizeTipWidth = resizeTipElem.clientWidth;
const resizeTipHeight = resizeTipElem.clientHeight;
let resizeBarLeft = Math.max(2, evnt.clientX - tableRect.x);
let resizeBarTop = 0;
if (resizeBarLeft + resizeTipWidth >= rtWidth - 2) {
resizeBarLeft = rtWidth - resizeTipWidth - 2;
}
if (dragTop + resizeTipHeight >= tableHeight) {
resizeBarTop = tableHeight - (dragTop + resizeTipHeight);
}
resizeTipElem.style.left = `${resizeBarLeft}px`;
resizeTipElem.style.top = `${resizeBarTop}px`;
}
reactData.isDragResize = true;
};
reactData.isDragResize = true;
addClass(tableEl, 'row-drag--resize');
resizeBarElem.style.display = 'block';
document.onmousemove = updateEvent;
document.onmouseup = function (evnt) {
document.onmousemove = null;
document.onmouseup = null;
resizeBarElem.style.display = 'none';
internalData._lastResizeTime = Date.now();
setTimeout(() => {
reactData.isDragResize = false;
}, 50);
if (resizeHeight !== currCellHeight) {
const resizeParams = Object.assign(Object.assign({}, params), { resizeHeight, resizeRow: row });
internalData.isResizeCellHeight = true;
if ($xeTable.handleRowResizeCellAreaEvent) {
$xeTable.handleRowResizeCellAreaEvent(evnt, resizeParams);
}
else {
rowRest.resizeHeight = resizeHeight;
handleUpdateRowResize(evnt, resizeParams);
updateRowOffsetTop();
}
}
removeClass(tableEl, 'row-drag--resize');
};
updateEvent(evnt);
},
/**
* @private
*/
handleRowResizeDblclickEvent(evnt, params) {
const resizableOpts = computeResizableOpts.value;
const { isDblclickAutoHeight } = resizableOpts;
const el = refElem.value;
if (isDblclickAutoHeight && el) {
evnt.stopPropagation();
evnt.preventDefault();
const { editStore } = reactData;
const { fullAllDataRowIdData } = internalData;
const { actived } = editStore;
const { row } = params;
const rowid = getRowid($xeTable, row);
const rowRest = fullAllDataRowIdData[rowid];
if (!rowRest) {
return;
}
const handleRsHeight = () => {
el.setAttribute('data-calc-row', 'Y');
const resizeHeight = calcCellAutoHeight(rowid, rowRest, el);
el.removeAttribute('data-calc-row');
const resizeParams = Object.assign(Object.assign({}, params), { resizeHeight, resizeRow: row });
reactData.isDragResize = false;
internalData._lastResizeTime = Date.now();
if ($xeTable.handleRowResizeDblclickCellAreaEvent) {
$xeTable.handleRowResizeDblclickCellAreaEvent(evnt, resizeParams);
}
else {
rowRest.resizeHeight = resizeHeight;
handleUpdateRowResize(evnt, resizeParams);
}
};
if (actived.row || actived.column) {
$xeTable.clearEdit().then(handleRsHeight);
}
else {
handleRsHeight();
}
}
},
/**
* @private
*/
saveCustomStore(type) {
const { customConfig } = props;
const tableId = computeTableId.value;
const customOpts = computeCustomOpts.value;
const { updateStore, storage } = customOpts;
const { isCustomAlign, isCustomHeaderAlign, isCustomFooterAlign, isCustomResizable, isCustomVisible, isCustomFixed, isCustomSort, isCustomAggGroup, isCustomAggFunc, isCustomPager } = handleCustomStoreConfig($xeTable);
if (type !== 'reset') {
// fix:修复拖动列宽,重置按钮无法点击的问题
reactData.isCustomStatus = true;
}
if (storage &&
(customConfig ? isEnableConf(customOpts) : customOpts.enabled) &&
(isCustomAlign ||
isCustomHeaderAlign ||
isCustomFooterAlign ||
isCustomResizable ||
isCustomVisible ||
isCustomFixed ||
isCustomSort ||
isCustomAggGroup ||
isCustomAggFunc ||
isCustomPager)) {
if (!tableId) {
errLog('vxe.error.reqProp', ['id']);
return nextTick();
}
const storeData = type === 'reset'
? {
pagerData: {},
alignData: {},
headerAlignData: {},
footerAlignData: {},
resizableData: {},
sortData: [],
visibleData: {},
fixedData: {},
aggGroupData: {},
aggFuncData: {}
}
: $xeTable.getCustomStoreData();
if (updateStore) {
return updateStore({
$table: $xeTable,
id: tableId,
type,
storeData
});
}
else {
setCustomStorageMap(tableId, type === 'reset' ? null : storeData);
}
}
return nextTick();
},
/**
* @private
*/
handleCustom() {
const { mouseConfig } = props;
if (mouseConfig) {
if ($xeTable.clearSelected) {
$xeTable.clearSelected();
}
if ($xeTable.clearCellAreas) {
$xeTable.clearCellAreas();
$xeTable.clearCopyCellArea();
}
}
$xeTable.analyColumnWidth();
return $xeTable.refreshColumn(true);
},
handleUpdateDataQueue() {
reactData.upDataFlag++;
},
handleRefreshColumnQueue() {
reactData.reColumnFlag++;
},
handleFilterOptions(column) {
if (column) {
const { filterStore } = reactData;
const { filterRender, filters } = column;
const filterOptions = filters || [];
const compConf = isEnableConf(filterRender) ? renderer.get(filterRender.name) : null;
const frMethod = column.filterRecoverMethod || (compConf ? (compConf.tableFilterRecoverMethod || compConf.filterRecoverMethod) : null);
filterStore.column = column;
// 复原状态
filterOptions.forEach((option) => {
const { _checked, checked } = option;
option._checked = checked;
if (!checked && _checked !== checked) {
if (frMethod) {
frMethod({ option, column, $table: $xeTable });
}
}
});
$xeTable.checkFilterOptions();
}
},
preventEvent(evnt, type, args, next, end) {
let evntList = interceptor.get(type);
// 兼容老版本
if (!evntList.length && type === 'event.clearEdit') {
evntList = interceptor.get('event.clearActived');
if (evntList.length) {
warnLog('vxe.error.delEvent', ['event.clearActived', 'event.clearEdit']);
}
}
// 兼容老版本
let rest = null;
let isStop = false;
for (let i = 0; i < evntList.length; i++) {
const func = evntList[i];
const fnRest = func(Object.assign({ $table: $xeTable, $grid: $xeGrid, gantt: $xeGantt, $event: evnt }, args));
if (fnRest === false) {
isStop = true;
break;
}
else if (fnRest && fnRest.status === false) {
rest = fnRest.result;
isStop = true;
break;
}
}
if (!isStop) {
if (next) {
rest = next();
}
}
if (end) {
end();
}
return rest;
},
updateCheckboxStatus() {
const { treeConfig } = props;
const { isRowGroupStatus } = reactData;
const { afterTreeFullData, afterGroupFullData, selectCheckboxMaps, treeIndeterminateRowMaps } = internalData;
const aggregateOpts = computeAggregateOpts.value;
const treeOpts = computeTreeOpts.value;
const childrenField = treeOpts.children || treeOpts.childrenField;
const checkboxOpts = computeCheckboxOpts.value;
const { checkField, indeterminateField, checkStrictly, checkMethod } = checkboxOpts;
if (checkStrictly) {
return;
}
if (isRowGroupStatus || treeConfig) {
const { handleGetRowId } = createHandleGetRowId($xeTable);
const childRowMaps = {};
const childRowList = [];
if (isRowGroupStatus) {
// 行分组
const mapChildrenField = aggregateOpts.mapChildrenField;
if (mapChildrenField) {
XEUtils.eachTree(afterGroupFullData, (row) => {
const rowid = handleGetRowId(row);
const childList = row[mapChildrenField];
if (childList && childList.length && !childRowMaps[rowid]) {
childRowMaps[rowid] = 1;
childRowList.unshift([row, rowid, childList]);
}
}, { children: mapChildrenField });
}
}
else if (treeConfig) {
// 树结构
const { transform, mapChildrenField } = treeOpts;
XEUtils.eachTree(afterTreeFullData, (row) => {
const rowid = handleGetRowId(row);
const childList = row[transform ? mapChildrenField : childrenField];
if (childList && childList.length && !childRowMaps[rowid]) {
childRowMaps[rowid] = 1;
childRowList.unshift([row, rowid, childList]);
}
else {
if (indeterminateField) {
XEUtils.set(row, indeterminateField, false);
}
}
}, { children: transform ? mapChildrenField : childrenField });
}
childRowList.forEach(vals => {
const row = vals[0];
const rowid = vals[1];
const childList = vals[2];
let sLen = 0; // 已选
let hLen = 0; // 半选
let vLen = 0; // 有效子行
const cLen = childList.length; // 子行
childList.forEach(checkMethod
? (item) => {
const childRowid = handleGetRowId(item);
const isSelect = checkField ? XEUtils.get(item, checkField) : selectCheckboxMaps[childRowid];
if (checkMethod({ $table: $xeTable, row: item })) {
if (isSelect) {
sLen++;
}
else if (treeIndeterminateRowMaps[childRowid]) {
hLen++;
}
vLen++;
}
else {
if (isSelect) {
sLen++;
}
else if (treeIndeterminateRowMaps[childRowid]) {
hLen++;
}
}
}
: item => {
const childRowid = handleGetRowId(item);
const isSelect = checkField ? XEUtils.get(item, checkField) : selectCheckboxMaps[childRowid];
if (isSelect) {
sLen++;
}
else if (treeIndeterminateRowMaps[childRowid]) {
hLen++;
}
vLen++;
});
let isSelected = false;
if (cLen > 0) {
if (vLen > 0) {
isSelected = (sLen > 0 || hLen > 0) && sLen >= vLen;
}
else {
// 如果存在子项禁用
if ((sLen > 0 && sLen >= vLen)) {
isSelected = true;
}
else if (selectCheckboxMaps[rowid]) {
isSelected = true;
}
else {
isSelected = false;
}
}
}
else {
// 如果无子项
isSelected = selectCheckboxMaps[rowid];
}
const halfSelect = !isSelected && (sLen > 0 || hLen > 0);
if (checkField) {
XEUtils.set(row, checkField, isSelected);
}
if (indeterminateField) {
XEUtils.set(row, indeterminateField, halfSelect);
}
if (isSelected) {
if (!checkField) {
selectCheckboxMaps[rowid] = row;
}
if (treeIndeterminateRowMaps[rowid]) {
delete treeIndeterminateRowMaps[rowid];
}
}
else {
if (!checkField) {
if (selectCheckboxMaps[rowid]) {
delete selectCheckboxMaps[rowid];
}
}
if (halfSelect) {
treeIndeterminateRowMaps[rowid] = row;
}
else {
if (treeIndeterminateRowMaps[rowid]) {
delete treeIndeterminateRowMaps[rowid];
}
}
}
});
}
reactData.updateCheckboxFlag++;
},
updateAllCheckboxStatus() {
const { treeConfig } = props;
const { isRowGroupStatus } = reactData;
const { afterFullData, afterTreeFullData, afterGroupFullData, checkboxReserveRowMap, selectCheckboxMaps, treeIndeterminateRowMaps } = internalData;
const aggregateOpts = computeAggregateOpts.value;
const { mapChildrenField } = aggregateOpts;
const checkboxOpts = computeCheckboxOpts.value;
const { checkField, checkMethod, showReserveStatus } = checkboxOpts;
const { handleGetRowId } = createHandleGetRowId($xeTable);
let sLen = 0; // 已选
let dsLen = 0; // 禁用的已选
let hLen = 0; // 半选
let dhLen = 0; // 禁用的半选
let vLen = 0; // 有效行
const rootList = (treeConfig ? afterTreeFullData : (isRowGroupStatus ? afterGroupFullData : afterFullData));
rootList.forEach(checkMethod
? row => {
const childRowid = handleGetRowId(row);
const selected = checkField ? XEUtils.get(row, checkField) : selectCheckboxMaps[childRowid];
if (isRowGroupStatus && $xeTable.isAggregateRecord(row)) {
const childList = row[mapChildrenField || ''];
if (selected) {
vLen++;
sLen++;
}
else if (treeIndeterminateRowMaps[childRowid]) {
vLen++;
hLen++;
}
else if (childList && childList.length && childList.some(item => checkMethod({ $table: $xeTable, row: item }))) {
vLen++;
}
}
else if (checkMethod({ $table: $xeTable, row })) {
if (selected) {
sLen++;
}
else if (treeIndeterminateRowMaps[childRowid]) {
hLen++;
}
vLen++;
}
else {
if (selected) {
dsLen++;
}
else if (treeIndeterminateRowMaps[childRowid]) {
dhLen++;
}
}
}
: row => {
const childRowid = handleGetRowId(row);
const selected = checkField ? XEUtils.get(row, checkField) : selectCheckboxMaps[childRowid];
if (selected) {
sLen++;
}
else if (treeIndeterminateRowMaps[childRowid]) {
hLen++;
}
vLen++;
});
const isSelected = rootList.length > 0 ? (vLen > 0 ? (sLen >= vLen) : (sLen >= rootList.length)) : false;
let halfSelect = !isSelected && (sLen > 0 || hLen > 0 || dsLen > 0 || dhLen > 0);
// 如果复选框启用保留记录,当保留数据存在时显示半选
if (!isSelected && !halfSelect && showReserveStatus) {
halfSelect = !XEUtils.isEmpty(checkboxReserveRowMap);
}
reactData.isAllSelected = isSelected;
reactData.isIndeterminate = halfSelect;
},
checkSelectionStatus() {
$xeTable.updateCheckboxStatus();
$xeTable.updateAllCheckboxStatus();
},
/**
* 切换选中
* 多选,行选中事件
*/
handleBatchSelectRows(rows, checked, isForce) {
const { treeConfig } = props;
const { isRowGroupStatus } = reactData;
const { selectCheckboxMaps } = internalData;
const aggregateOpts = computeAggregateOpts.value;
const treeOpts = computeTreeOpts.value;
const { transform, mapChildrenField } = treeOpts;
const childrenField = treeOpts.children || treeOpts.childrenField;
const checkboxOpts = computeCheckboxOpts.value;
const { checkField, checkStrictly, checkMethod } = checkboxOpts;
const { handleGetRowId } = createHandleGetRowId($xeTable);
// indeterminateField 仅支持读取
const indeterminateField = checkboxOpts.indeterminateField || checkboxOpts.halfField;
if (checkField) {
// 树结构
if ((treeConfig || isRowGroupStatus) && !checkStrictly) {
// 更新子节点状态
XEUtils.eachTree(rows, (row) => {
if (isForce || (!checkMethod || checkMethod({ $table: $xeTable, row }))) {
XEUtils.set(row, checkField, checked);
if (indeterminateField) {
XEUtils.set(row, indeterminateField, false);
}
handleCheckboxReserveRow(row, checked);
}
}, { children: transform ? mapChildrenField : childrenField });
reactData.updateCheckboxFlag++;
return;
}
// 列表
rows.forEach(row => {
if (isForce || (!checkMethod || checkMethod({ $table: $xeTable, row }))) {
XEUtils.set(row, checkField, checked);
handleCheckboxReserveRow(row, checked);
}
});
reactData.updateCheckboxFlag++;
return;
}
// 树结构
if (!checkStrictly) {
if (isRowGroupStatus) {
// 更新行分组节点状态
XEUtils.eachTree(rows, (row) => {
const rowid = handleGetRowId(row);
if (isForce || (!checkMethod || checkMethod({ $table: $xeTable, row }))) {
if (checked) {
selectCheckboxMaps[rowid] = row;
}
else {
if (selectCheckboxMaps[rowid]) {
delete selectCheckboxMaps[rowid];
}
}
handleCheckboxReserveRow(row, checked);
}
}, { children: aggregateOpts.mapChildrenField });
reactData.updateCheckboxFlag++;
return;
}
else if (treeConfig) {
// 更新子节点状态
XEUtils.eachTree(rows, (row) => {
const rowid = handleGetRowId(row);
if (isForce || (!checkMethod || checkMethod({ $table: $xeTable, row }))) {
if (checked) {
selectCheckboxMaps[rowid] = row;
}
else {
if (selectCheckboxMaps[rowid]) {
delete selectCheckboxMaps[rowid];
}
}
handleCheckboxReserveRow(row, checked);
}
}, { children: transform ? mapChildrenField : childrenField });
reactData.updateCheckboxFlag++;
return;
}
}
// 列表
rows.forEach(row => {
const rowid = handleGetRowId(row);
if (isForce || (!checkMethod || checkMethod({ $table: $xeTable, row }))) {
if (checked) {
if (!selectCheckboxMaps[rowid]) {
selectCheckboxMaps[rowid] = row;
}
}
else {
if (selectCheckboxMaps[rowid]) {
delete selectCheckboxMaps[rowid];
}
}
handleCheckboxReserveRow(row, checked);
reactData.updateCheckboxFlag++;
}
});
},
/**
* 即将移除
* @deprecated
*/
handleSelectRow({ row }, checked, isForce) {
$xeTable.handleBatchSelectRows([row], checked, isForce);
},
handleUpdateHeaderMerge() {
const { mergeHeaderList } = internalData;
const { mergeMaps, mergeRowMaps, mergeColMaps } = buildMergeData(mergeHeaderList);
internalData.mergeHeaderCellMaps = mergeMaps;
internalData.mergeHeaderRowMaps = mergeRowMaps;
internalData.mergeHeaderColMaps = mergeColMaps;
reactData.mergeHeadFlag++;
},
/**
* 处理合并
*/
handleUpdateBodyMerge() {
const { mergeBodyList } = internalData;
const { mergeMaps, mergeRowMaps, mergeColMaps } = buildMergeData(mergeBodyList);
internalData.mergeBodyCellMaps = mergeMaps;
internalData.mergeBodyRowMaps = mergeRowMaps;
internalData.mergeBodyColMaps = mergeColMaps;
reactData.mergeBodyFlag++;
},
handleUpdateFooterMerge() {
const { mergeFooterList } = internalData;
const { mergeMaps, mergeRowMaps, mergeColMaps } = buildMergeData(mergeFooterList);
internalData.mergeFooterCellMaps = mergeMaps;
internalData.mergeFooterRowMaps = mergeRowMaps;
internalData.mergeFooterColMaps = mergeColMaps;
reactData.mergeFootFlag++;
},
handleAggregateSummaryData() {
return $xeTable.refreshAggregateCalcValues();
},
triggerHeaderTitleEvent(evnt, iconParams, params) {
const tipContent = iconParams.content || iconParams.message;
if (tipContent) {
const { tooltipStore } = reactData;
const { column } = params;
const content = getFuncText(tipContent);
handleTargetEnterEvent(true);
tooltipStore.row = null;
tooltipStore.column = column;
tooltipStore.visible = true;
tooltipStore.currOpts = iconParams;
nextTick(() => {
const $tooltip = refTooltip.value;
if ($tooltip && $tooltip.open) {
$tooltip.open(evnt.currentTarget, content);
}
});
}
},
/**
* 触发表头 tooltip 事件
*/
triggerHeaderTooltipEvent(evnt, params) {
const { tooltipStore } = reactData;
const headerTooltipOpts = computeHeaderTooltipOpts.value;
const { column } = params;
handleTargetEnterEvent(true);
const titleElem = evnt.currentTarget;
if (!titleElem) {
return;
}
const cWrapperEl = titleElem.parentElement;
if (!cWrapperEl) {
return;
}
const cellEl = cWrapperEl.parentElement;
if (!cellEl) {
return;
}
const thEl = cellEl.parentElement;
if (!thEl) {
return;
}
if (tooltipStore.column !== column || !tooltipStore.visible) {
const ctEl = thEl.querySelector('.vxe-cell--title');
handleTooltip(evnt, headerTooltipOpts, 'header', thEl, (hasClass(thEl, 'col--ellipsis') ? ctEl : cWrapperEl) || cWrapperEl, ctEl || cellEl, params);
}
},
/**
* 触发单元格 tooltip 事件
*/
triggerBodyTooltipEvent(evnt, params) {
const { editConfig } = props;
const { editStore } = reactData;
const { tooltipStore } = reactData;
const tooltipOpts = computeTooltipOpts.value;
const editOpts = computeEditOpts.value;
const { actived } = editStore;
const { row, column } = params;
const tdEl = evnt.currentTarget;
handleTargetEnterEvent(tooltipStore.column !== column || tooltipStore.row !== row);
// 单元格处于编辑状态时不触发提示框
if (column.editRender && isEnableConf(editConfig)) {
// 如果是行编辑模式
if (editOpts.mode === 'row' && actived.row === row) {
return;
}
// 如果是单元格编辑模式
if (actived.row === row && actived.column === column) {
return;
}
}
if (tooltipStore.column !== column || tooltipStore.row !== row || !tooltipStore.visible) {
const ctEl = tdEl.querySelector('.vxe-cell--wrapper');
let ovEl = null;
let tipEl = tdEl.querySelector(column.type === 'html' ? '.vxe-cell--html' : '.vxe-cell--label');
if (column.treeNode) {
ovEl = tdEl.querySelector('.vxe-tree-cell');
}
if (!tipEl) {
tipEl = ctEl;
}
handleTooltip(evnt, tooltipOpts, 'body', tdEl, ovEl || ctEl, tipEl, params);
}
},
/**
* 触发表尾 tooltip 事件
*/
triggerFooterTooltipEvent(evnt, params) {
const { column } = params;
const { tooltipStore } = reactData;
const footerTooltipOpts = computeFooterTooltipOpts.value;
const tdEl = evnt.currentTarget;
handleTargetEnterEvent(tooltipStore.column !== column || !!tooltipStore.row);
if (tooltipStore.column !== column || !tooltipStore.visible) {
const ctEl = tdEl.querySelector('.vxe-cell--wrapper');
let ovEl = null;
let tipEl = tdEl.querySelector(column.type === 'html' ? '.vxe-cell--html' : '.vxe-cell--label');
if (column.type === 'html') {
ovEl = tdEl.querySelector('.vxe-cell--html');
}
if (!tipEl) {
tipEl = ctEl;
}
handleTooltip(evnt, footerTooltipOpts, 'footer', tdEl, ovEl || ctEl, tipEl, params);
}
},
handleTargetLeaveEvent() {
const tooltipOpts = computeTooltipOpts.value;
let $tooltip = refTooltip.value;
if ($tooltip && $tooltip.setActived) {
$tooltip.setActived(false);
}
if (tooltipOpts.enterable) {
internalData.tooltipTimeout = setTimeout(() => {
$tooltip = refTooltip.value;
if ($tooltip && $tooltip.isActived && !$tooltip.isActived()) {
$xeTable.closeTooltip();
}
}, tooltipOpts.leaveDelay);
}
else {
$xeTable.closeTooltip();
}
},
triggerHeaderCellClickEvent(evnt, params) {
const { _lastResizeTime } = internalData;
const sortOpts = computeSortOpts.value;
const columnOpts = computeColumnOpts.value;
const currentColumnOpts = computeCurrentColumnOpts.value;
const { column } = params;
const cell = evnt.currentTarget;
const triggerResizable = _lastResizeTime && _lastResizeTime > Date.now() - 300;
const triggerSort = getEventTargetNode(evnt, cell, 'vxe-cell--sort').flag;
const triggerFilter = getEventTargetNode(evnt, cell, 'vxe-cell--filter').flag;
if (sortOpts.trigger === 'cell' && !(triggerResizable || triggerSort || triggerFilter)) {
$xeTable.triggerSortEvent(evnt, column, getNextSortOrder(column));
}
if ($xeGantt) {
const ganttReactData = $xeGantt.reactData;
ganttReactData.activeBarRowid = null;
}
dispatchEvent('header-cell-click', Object.assign({ triggerResizable, triggerSort, triggerFilter, cell }, params), evnt);
if ((columnOpts.isCurrent || props.highlightCurrentColumn) && (!currentColumnOpts.trigger || ['header', 'default'].includes(currentColumnOpts.trigger))) {
$xeTable.triggerCurrentColumnEvent(evnt, params);
}
},
triggerHeaderCellDblclickEvent(evnt, params) {
dispatchEvent('header-cell-dblclick', Object.assign({ cell: evnt.currentTarget }, params), evnt);
},
/**
* 列点击事件
* 如果是单击模式,则激活为编辑状态
* 如果是双击模式,则单击后选中状态
*/
triggerCellClickEvent(evnt, params) {
const { treeConfig, highlightCurrentRow, highlightCurrentColumn, editConfig, aggregateConfig, rowGroupConfig } = props;
const { editStore, isDragResize, expandColumn, checkboxColumn, radioColumn } = reactData;
if (isDragResize) {
return;
}
const expandOpts = computeExpandOpts.value;
const editOpts = computeEditOpts.value;
const treeOpts = computeTreeOpts.value;
const radioOpts = computeRadioOpts.value;
const checkboxOpts = computeCheckboxOpts.value;
const keyboardOpts = computeKeyboardOpts.value;
const aggregateOpts = computeAggregateOpts.value;
const rowOpts = computeRowOpts.value;
const columnOpts = computeColumnOpts.value;
const currentColumnOpts = computeCurrentColumnOpts.value;
const { actived, focused } = editStore;
const { row, column } = params;
const { type, treeNode, rowGroupNode } = column;
const isRadioType = type === 'radio';
const isCheckboxType = type === 'checkbox';
const isExpandType = type === 'expand';
const cell = evnt.currentTarget;
const triggerRadio = isRadioType && getEventTargetNode(evnt, cell, 'vxe-cell--radio').flag;
const triggerCheckbox = isCheckboxType && getEventTargetNode(evnt, cell, 'vxe-cell--checkbox').flag;
const triggerTreeNode = treeNode && getEventTargetNode(evnt, cell, 'vxe-cell--tree-btn').flag;
const triggerExpandNode = isExpandType && getEventTargetNode(evnt, cell, 'vxe-table--expanded').flag;
const triggerRowGroupNode = isExpandType && getEventTargetNode(evnt, cell, 'vxe-row-group--node-btn').flag;
params = Object.assign({ cell, triggerRadio, triggerCheckbox, triggerTreeNode, triggerExpandNode }, params);
if (!triggerCheckbox && !triggerRadio) {
// 如果是展开行
if (!triggerExpandNode && ((expandColumn && expandOpts.trigger === 'row') || (isExpandType && expandOpts.trigger === 'cell'))) {
$xeTable.triggerRowExpandEvent(evnt, params);
}
// 如果是树形表格
if (treeConfig && (treeOpts.trigger === 'row' || (treeNode && treeOpts.trigger === 'cell'))) {
$xeTable.triggerTreeExpandEvent(evnt, params);
}
// 如果是行分组
if ((aggregateConfig || rowGroupConfig) && (aggregateOpts.trigger === 'row' || (rowGroupNode && aggregateOpts.trigger === 'cell'))) {
$xeTable.triggerRowGroupExpandEvent(evnt, params);
}
}
// 如果点击了树节点
if (!triggerTreeNode) {
if (!triggerExpandNode && !triggerRowGroupNode) {
// 如果是当前行
if (rowOpts.isCurrent || highlightCurrentRow) {
if (!triggerCheckbox && !triggerRadio) {
$xeTable.triggerCurrentRowEvent(evnt, params);
}
}
// 如果是当前列
if ((columnOpts.isCurrent || highlightCurrentColumn) && (!currentColumnOpts.trigger || ['cell', 'default'].includes(currentColumnOpts.trigger))) {
if (!triggerCheckbox && !triggerRadio) {
$xeTable.triggerCurrentColumnEvent(evnt, params);
}
}
// 如果是单选框
if (!triggerRadio && ((radioColumn && radioOpts.trigger === 'row') || (isRadioType && radioOpts.trigger === 'cell'))) {
$xeTable.triggerRadioRowEvent(evnt, params);
}
// 如果是复选框
if (!triggerCheckbox && ((checkboxColumn && checkboxOpts.trigger === 'row') || (isCheckboxType && checkboxOpts.trigger === 'cell'))) {
$xeTable.handleToggleCheckRowEvent(evnt, params);
}
}
// 如果设置了单元格选中功能,则不会使用点击事件去处理(只能支持双击模式)
if (isEnableConf(editConfig)) {
// 记录点击输入框聚焦状态
if (keyboardOpts.arrowCursorLock && evnt && editOpts.mode === 'cell' && evnt.target && /^input|textarea$/i.test(evnt.target.tagName)) {
focused.column = column;
focused.row = row;
}
if (editOpts.trigger === 'manual') {
if (actived.args && actived.row === row && column !== actived.column) {
if (editOpts.mode === 'row') {
handleChangeCell(evnt, params);
}
else {
checkValidate('blur')
.catch((e) => e);
}
}
}
else if (!actived.args || row !== actived.row || column !== actived.column) {
if (editOpts.trigger === 'click') {
handleChangeCell(evnt, params);
}
else if (editOpts.trigger === 'dblclick') {
if (editOpts.mode === 'row' && actived.row === row) {
handleChangeCell(evnt, params);
}
}
}
}
}
// 如果是双击编辑模式
if (isEnableConf(editConfig) && editOpts.trigger === 'dblclick') {
if (actived.row && actived.column) {
if (editOpts.mode === 'row') {
if (!$xeTable.eqRow(actived.row, row)) {
$xeTable.handleClearEdit(evnt);
}
}
else if (editOpts.mode === 'cell') {
if (!$xeTable.eqRow(actived.row, row) || actived.column.id !== column.id) {
$xeTable.handleClearEdit(evnt);
}
}
}
}
if ($xeGantt) {
const ganttReactData = $xeGantt.reactData;
ganttReactData.activeBarRowid = null;
}
dispatchEvent('cell-click', params, evnt);
},
/**
* 列双击点击事件
* 如果是双击模式,则激活为编辑状态
*/
triggerCellDblclickEvent(evnt, params) {
const { editConfig } = props;
const { editStore, isDragResize } = reactData;
if (isDragResize) {
return;
}
const editOpts = computeEditOpts.value;
const { actived } = editStore;
const cell = evnt.currentTarget;
params = Object.assign({ cell }, params);
if (isEnableConf(editConfig) && editOpts.trigger === 'dblclick') {
if (!actived.args || evnt.currentTarget !== actived.args.cell) {
if (editOpts.mode === 'row') {
checkValidate('blur')
.catch((e) => e)
.then(() => {
$xeTable.handleEdit(params, evnt)
.then(() => checkValidate('change'))
.catch((e) => e);
});
}
else if (editOpts.mode === 'cell') {
$xeTable.handleEdit(params, evnt)
.then(() => checkValidate('change'))
.catch((e) => e);
}
}
}
dispatchEvent('cell-dblclick', params, evnt);
},
triggerFooterCellClickEvent(evnt, params) {
const cell = evnt.currentTarget;
params = Object.assign({ cell }, params);
if ($xeGantt) {
const ganttReactData = $xeGantt.reactData;
ganttReactData.activeBarRowid = null;
}
$xeTable.dispatchEvent('footer-cell-click', params, evnt);
},
triggerFooterCellDblclickEvent(evnt, params) {
const cell = evnt.currentTarget;
params = Object.assign({ cell }, params);
$xeTable.dispatchEvent('footer-cell-dblclick', params, evnt);
},
handleToggleCheckRowEvent(evnt, params) {
const { selectCheckboxMaps } = internalData;
const checkboxOpts = computeCheckboxOpts.value;
const { checkField, trigger } = checkboxOpts;
const { row } = params;
if (trigger === 'manual') {
return;
}
let checked = false;
if (checkField) {
checked = !XEUtils.get(row, checkField);
}
else {
checked = !selectCheckboxMaps[getRowid($xeTable, row)];
}
if (evnt) {
$xeTable.triggerCheckRowEvent(evnt, params, checked);
}
else {
$xeTable.handleBatchSelectRows([row], checked);
$xeTable.checkSelectionStatus();
}
},
triggerCheckRowEvent(evnt, params, checked) {
const { treeConfig } = props;
const { row } = params;
const { isRowGroupStatus } = reactData;
const { fullAllDataRowIdData, afterFullData, afterTreeFullData, afterGroupFullData } = internalData;
const checkboxOpts = computeCheckboxOpts.value;
const aggregateOpts = computeAggregateOpts.value;
const treeOpts = computeTreeOpts.value;
const { checkMethod, trigger, checkStrictly } = checkboxOpts;
if (trigger === 'manual') {
return;
}
evnt.stopPropagation();
if (checkboxOpts.isShiftKey && evnt.shiftKey) {
const { handleGetRowId } = createHandleGetRowId($xeTable);
const checkboxRecords = $xeTable.getCheckboxRecords();
let currSeq = -1;
let currRow = null;
const currRowid = handleGetRowId(row);
const rowRest = fullAllDataRowIdData[currRowid];
if (rowRest) {
currRow = rowRest.row;
currSeq = rowRest._seq;
}
if (currRow && checkboxRecords.length) {
let rangeRows = [];
let firstSeq = -1;
let firstRow = null;
let firstRowid = '';
let lastSeq = -1;
let lastRow = null;
let lastRowid = '';
// 根据序号取出范围最小/最大的行
const selectMaps = {};
checkboxRecords.forEach(item => {
const rowid = handleGetRowId(item);
const rowRest = fullAllDataRowIdData[rowid];
if (rowRest) {
if (!firstRow || firstSeq > rowRest._seq) {
firstRowid = rowRest.rowid;
firstRow = rowRest.row;
firstSeq = rowRest._seq;
}
if (!lastRow || lastSeq < rowRest._seq) {
lastRowid = rowRest.rowid;
lastRow = rowRest.row;
lastSeq = rowRest._seq;
}
}
selectMaps[rowid] = item;
});
// 如果已选只有一条并选择当前则跳过
if (firstRow && lastRow && (checkboxRecords.length > 1 || currRowid !== firstRowid) && (Math.abs(firstSeq - lastSeq) > 1 || Math.abs(currSeq - firstSeq) > 1 || Math.abs(currSeq - lastSeq) > 1)) {
// 树与分组
if (treeConfig || isRowGroupStatus) {
const { transform } = treeOpts;
const childrenField = treeOpts.children || treeOpts.childrenField;
const iteratorChildField = treeConfig ? (transform ? treeOpts.mapChildrenField : childrenField) : aggregateOpts.mapChildrenField;
let isMatchFirst = false;
let matchStartRowid = '';
let matchEndRowid = '';
const handleGetChildRowid = (rowid, isLast) => {
const rowRest = fullAllDataRowIdData[rowid];
if (rowRest) {
const item = rowRest.row;
const childList = item[iteratorChildField];
if (childList && childList.length) {
const targetRow = isLast ? XEUtils.last(childList) : XEUtils.first(childList);
return handleGetChildRowid(handleGetRowId(targetRow), isLast);
}
}
return rowid;
};
const handleGetSelectParentRowid = (rowid) => {
const rowRest = fullAllDataRowIdData[rowid];
if (rowRest) {
const parentItem = rowRest.parent;
if (parentItem) {
const parentRowid = handleGetRowId(parentItem);
if (selectMaps[parentRowid]) {
return handleGetSelectParentRowid(parentRowid);
}
}
}
return rowid;
};
const handleGetRootRow = (row) => {
const rowid = handleGetRowId(row);
if (rowid) {
const rest = fullAllDataRowIdData[rowid];
if (rest) {
return rest.parent ? handleGetRootRow(rest.parent) : rest;
}
}
return null;
};
if (currSeq < firstSeq) {
matchStartRowid = handleGetChildRowid(currRowid, 0);
matchEndRowid = handleGetChildRowid(firstRowid, 1);
}
else {
if (currSeq > lastSeq) {
matchStartRowid = handleGetSelectParentRowid(lastRowid);
}
else {
matchStartRowid = handleGetChildRowid(firstRowid, 0);
}
matchEndRowid = handleGetChildRowid(currRowid, 1);
}
const handleRangeRow = (item) => {
const rowid = handleGetRowId(item);
const childList = item[iteratorChildField];
if (!isMatchFirst && rowid === matchStartRowid) {
isMatchFirst = true;
}
// 如果是父子关联,则排除父节点
if (isMatchFirst && (checkStrictly || !childList || !childList.length)) {
rangeRows.push(item);
}
// break
return rowid === matchEndRowid;
};
if (treeConfig) {
const matchStartRowRest = fullAllDataRowIdData[matchStartRowid];
const firstRootRowRest = matchStartRowRest ? handleGetRootRow(matchStartRowRest.row) : null;
if (firstRootRowRest) {
// 优化查找复杂度
XEUtils.findTree(afterTreeFullData.slice(firstRootRowRest.treeIndex), handleRangeRow, { children: iteratorChildField });
}
else {
XEUtils.findTree(afterTreeFullData, handleRangeRow, { children: iteratorChildField });
}
}
else {
XEUtils.findTree(afterGroupFullData, handleRangeRow, { children: iteratorChildField });
}
}
else {
const _currRowIndex = $xeTable.getVTRowIndex(currRow);
const _firstRowIndex = $xeTable.getVTRowIndex(firstRow);
const _lastRowIndex = $xeTable.getVTRowIndex(lastRow);
if (_currRowIndex < _firstRowIndex) {
rangeRows = afterFullData.slice(_currRowIndex, _firstRowIndex + 1);
}
else if (_currRowIndex > _lastRowIndex) {
rangeRows = afterFullData.slice(_lastRowIndex, _currRowIndex + 1);
}
else {
rangeRows = afterFullData.slice(_firstRowIndex, _currRowIndex + 1);
}
}
$xeTable.setAllCheckboxRow(false);
nextTick(() => {
handleCheckedCheckboxRow(rangeRows, true, false);
});
dispatchEvent('checkbox-range-select', Object.assign({ rangeRecords: rangeRows }, params), evnt);
}
}
}
if (!checkMethod || checkMethod({ $table: $xeTable, row })) {
$xeTable.handleBatchSelectRows([row], checked);
$xeTable.checkSelectionStatus();
dispatchEvent('checkbox-change', Object.assign({
records: () => $xeTable.getCheckboxRecords(),
reserves: () => $xeTable.getCheckboxReserveRecords(),
indeterminates: () => $xeTable.getCheckboxIndeterminateRecords(),
checked
}, params), evnt);
}
},
/**
* 多选,选中所有事件
*/
triggerCheckAllEvent(evnt, value) {
const checkboxOpts = computeCheckboxOpts.value;
const { trigger } = checkboxOpts;
if (trigger === 'manual') {
return;
}
if (evnt) {
evnt.stopPropagation();
}
handleCheckAllEvent(evnt, value);
},
/**
* 单选,行选中事件
*/
triggerRadioRowEvent(evnt, params) {
const { selectRadioRow: oldValue } = reactData;
const { row } = params;
const radioOpts = computeRadioOpts.value;
const { trigger, strict, checkMethod } = radioOpts;
if (trigger === 'manual') {
return;
}
evnt.stopPropagation();
if (!checkMethod || checkMethod({ $table: $xeTable, row })) {
let newValue = row;
let isChange = oldValue !== newValue;
if (strict) {
handleCheckedRadioRow(newValue, false);
}
else {
if (oldValue === newValue) {
newValue = null;
}
isChange = oldValue !== newValue;
if (isChange && newValue) {
handleCheckedRadioRow(newValue, false);
}
else {
newValue = null;
$xeTable.clearRadioRow();
}
}
if (isChange) {
dispatchEvent('radio-change', Object.assign({ oldValue, newValue, selected: !!newValue }, params), evnt);
}
}
},
triggerCurrentColumnEvent(evnt, params) {
const { currentColumn: oldValue } = reactData;
const columnOpts = computeColumnOpts.value;
const currentColumnOpts = computeCurrentColumnOpts.value;
const beforeRowMethod = currentColumnOpts.beforeSelectMethod || columnOpts.currentMethod;
let newValue = params.column;
const { trigger, strict } = currentColumnOpts;
if (trigger === 'manual') {
return;
}
let isChange = oldValue !== newValue;
if (!beforeRowMethod || beforeRowMethod({ column: newValue, $table: $xeTable })) {
if (strict) {
$xeTable.setCurrentColumn(newValue);
}
else {
if (oldValue === newValue) {
newValue = null;
}
isChange = oldValue !== newValue;
if (isChange && newValue) {
$xeTable.setCurrentColumn(newValue);
}
else {
newValue = null;
$xeTable.clearCurrentColumn();
}
}
if (isChange) {
dispatchEvent('current-column-change', Object.assign({ oldValue, newValue, selected: !!newValue }, params), evnt);
}
}
else {
dispatchEvent('current-column-disabled', params, evnt);
}
},
triggerCurrentRowEvent(evnt, params) {
const { currentRow: oldValue } = internalData;
const rowOpts = computeRowOpts.value;
const currentRowOpts = computeCurrentRowOpts.value;
const beforeRowMethod = currentRowOpts.beforeSelectMethod || rowOpts.currentMethod;
let { row: newValue } = params;
const { trigger, strict } = currentRowOpts;
if (trigger === 'manual') {
return;
}
let isChange = oldValue !== newValue;
if (!beforeRowMethod || beforeRowMethod({ row: newValue, $table: $xeTable })) {
if (strict) {
$xeTable.setCurrentRow(newValue);
}
else {
if (oldValue === newValue) {
newValue = null;
}
isChange = oldValue !== newValue;
if (isChange && newValue) {
$xeTable.setCurrentRow(newValue);
}
else {
newValue = null;
$xeTable.clearCurrentRow();
}
}
if (isChange) {
dispatchEvent('current-row-change', Object.assign({ oldValue, newValue, selected: !!newValue }, params), evnt);
// 已废弃
dispatchEvent('current-change', Object.assign({ oldValue, newValue }, params), evnt);
}
}
else {
dispatchEvent('current-row-disabled', params, evnt);
}
},
/**
* 展开行事件
*/
triggerRowExpandEvent(evnt, params) {
const { expandColumn } = reactData;
const { rowExpandLazyLoadedMaps } = internalData;
const expandOpts = computeExpandOpts.value;
const { row } = params;
const { lazy, trigger } = expandOpts;
if (trigger === 'manual') {
return;
}
evnt.stopPropagation();
const rowid = getRowid($xeTable, row);
if (!lazy || !rowExpandLazyLoadedMaps[rowid]) {
const expanded = !$xeTable.isRowExpandByRow(row);
const columnIndex = expandColumn ? $xeTable.getColumnIndex(expandColumn) : -1;
const $columnIndex = expandColumn ? $xeTable.getVMColumnIndex(expandColumn) : -1;
$xeTable.setRowExpand(row, expanded);
dispatchEvent('toggle-row-expand', {
expanded,
column: expandColumn,
columnIndex,
$columnIndex,
row,
rowIndex: $xeTable.getRowIndex(row),
$rowIndex: $xeTable.getVMRowIndex(row)
}, evnt);
}
},
/**
* 行分组事件
*/
triggerRowGroupExpandEvent(evnt, params) {
const { rowGroupExpandedMaps } = internalData;
const aggregateOpts = computeAggregateOpts.value;
const { row, column } = params;
const { trigger } = aggregateOpts;
if (trigger === 'manual') {
return;
}
evnt.stopPropagation();
const rowid = getRowid($xeTable, row);
const expanded = !rowGroupExpandedMaps[rowid];
const columnIndex = $xeTable.getColumnIndex(column);
const $columnIndex = $xeTable.getVMColumnIndex(column);
$xeTable.setRowGroupExpand(row, expanded);
dispatchEvent('toggle-row-group-expand', { expanded, column, columnIndex, $columnIndex, row }, evnt);
},
/**
* 展开树节点事件
*/
triggerTreeExpandEvent(evnt, params) {
const { treeExpandLazyLoadedMaps, treeEATime } = internalData;
const treeOpts = computeTreeOpts.value;
const { row, column } = params;
const { lazy, trigger, accordion } = treeOpts;
if (trigger === 'manual') {
return;
}
evnt.stopPropagation();
const rowid = getRowid($xeTable, row);
if (!lazy || !treeExpandLazyLoadedMaps[rowid]) {
const expanded = !$xeTable.isTreeExpandByRow(row);
const columnIndex = $xeTable.getColumnIndex(column);
const $columnIndex = $xeTable.getVMColumnIndex(column);
if (treeEATime) {
clearTimeout(treeEATime);
}
$xeTable.setTreeExpand(row, expanded).then(() => {
if (accordion) {
internalData.treeEATime = setTimeout(() => {
internalData.treeEATime = undefined;
$xeTable.scrollToRow(row);
}, 30);
}
});
dispatchEvent('toggle-tree-expand', { expanded, column, columnIndex, $columnIndex, row }, evnt);
}
},
handleColumnSortEvent(evnt, column) {
const { mouseConfig } = props;
const mouseOpts = computeMouseOpts.value;
const { field, sortable, order } = column;
if (sortable) {
const params = { $table: $xeTable, $event: evnt, column, field, property: field, order, sortList: $xeTable.getSortColumns(), sortTime: column.sortTime };
if (mouseConfig && mouseOpts.area && $xeTable.handleSortEvent) {
$xeTable.handleSortEvent(evnt, params);
}
if (!order) {
dispatchEvent('clear-sort', params, evnt);
}
dispatchEvent('sort-change', params, evnt);
}
},
/**
* 点击排序事件
*/
triggerSortEvent(evnt, column, order) {
const sortOpts = computeSortOpts.value;
const { multiple, allowClear } = sortOpts;
const { field, sortable } = column;
if (sortable) {
if (!order || column.order === order) {
if (allowClear) {
$xeTable.clearSort(multiple ? column : null);
}
}
else {
$xeTable.sort({ field, order });
}
$xeTable.handleColumnSortEvent(evnt, column);
}
},
handleCellRuleUpdateStatus(type, cellParams, cellValue) {
const { validStore } = reactData;
const { row, column } = cellParams;
if ($xeTable.hasCellRules) {
if ($xeTable.hasCellRules(type, row, column)) {
const cell = $xeTable.getCellElement(row, column);
if (cell) {
const customVal = !XEUtils.isUndefined(cellValue);
return $xeTable.validCellRules(type, row, column, cellValue)
.then(() => {
if (customVal && validStore.visible) {
setCellValue(row, column, cellValue);
}
$xeTable.clearValidate(row, column);
})
.catch(({ rule }) => {
if (customVal) {
setCellValue(row, column, cellValue);
}
$xeTable.showValidTooltip({ rule, row, column, cell });
});
}
}
}
return nextTick();
},
/**
* 表头单元格按下事件
*/
triggerHeaderCellMousedownEvent(evnt, params) {
const { mouseConfig } = props;
const mouseOpts = computeMouseOpts.value;
const columnOpts = computeColumnOpts.value;
const columnDragOpts = computeColumnDragOpts.value;
const { trigger, isCrossDrag, isPeerDrag, disabledMethod } = columnDragOpts;
const cell = evnt.currentTarget;
const triggerInput = cell && cell.tagName && cell.tagName.toLowerCase() === 'input';
const triggerCheckbox = getEventTargetNode(evnt, cell, 'vxe-cell--checkbox').flag;
const triggerSort = getEventTargetNode(evnt, cell, 'vxe-cell--sort').flag;
const triggerFilter = getEventTargetNode(evnt, cell, 'vxe-cell--filter').flag;
let triggerDrag = false;
const isColDragCell = columnOpts.drag && trigger === 'cell';
if (!(triggerInput || triggerCheckbox || triggerSort || triggerFilter)) {
const { column } = params;
if (isColDragCell && !column.fixed && (isCrossDrag || isPeerDrag || !column.parentId) && !(disabledMethod && disabledMethod(params))) {
triggerDrag = true;
$xeTable.handleHeaderCellDragMousedownEvent(evnt, params);
}
}
if (!triggerDrag && mouseConfig && mouseOpts.area && $xeTable.handleHeaderCellAreaMouseDnEvent) {
$xeTable.handleHeaderCellAreaMouseDnEvent(evnt, Object.assign({ cell, triggerSort, triggerFilter }, params));
}
$xeTable.focus();
if ($xeTable.closeMenu) {
$xeTable.closeMenu();
}
},
/**
* 单元格按下事件
*/
triggerCellMousedownEvent(evnt, params) {
const { column } = params;
const { type, treeNode } = column;
const isRadioType = type === 'radio';
const isCheckboxType = type === 'checkbox';
const isExpandType = type === 'expand';
const rowOpts = computeRowOpts.value;
const rowDragOpts = computeRowDragOpts.value;
const { trigger, isCrossDrag, isPeerDrag, disabledMethod } = rowDragOpts;
const cell = evnt.currentTarget;
params.cell = cell;
const triggerInput = cell && cell.tagName && cell.tagName.toLowerCase() === 'input';
const triggerRadio = isRadioType && getEventTargetNode(evnt, cell, 'vxe-cell--radio').flag;
const triggerCheckbox = isCheckboxType && getEventTargetNode(evnt, cell, 'vxe-cell--checkbox').flag;
const triggerTreeNode = treeNode && getEventTargetNode(evnt, cell, 'vxe-cell--tree-btn').flag;
const triggerExpandNode = isExpandType && getEventTargetNode(evnt, cell, 'vxe-table--expanded').flag;
let isColDragCell = false;
if (rowOpts.drag) {
isColDragCell = trigger === 'row' || (column.dragSort && trigger === 'cell');
}
let triggerDrag = false;
if (!(triggerInput || triggerRadio || triggerCheckbox || triggerTreeNode || triggerExpandNode)) {
if (isColDragCell && (isCrossDrag || isPeerDrag || !params.level) && !(disabledMethod && disabledMethod(params))) {
triggerDrag = true;
$xeTable.handleCellDragMousedownEvent(evnt, params);
}
}
if (!triggerDrag && $xeTable.handleCellMousedownEvent) {
$xeTable.handleCellMousedownEvent(evnt, params);
}
$xeTable.focus();
$xeTable.closeFilter();
if ($xeTable.closeMenu) {
$xeTable.closeMenu();
}
},
triggerCellMouseupEvent() {
clearDragStatus();
},
/**
* 行拖拽
*/
handleRowDragDragstartEvent(evnt) {
if (evnt.dataTransfer) {
evnt.dataTransfer.setDragImage(getTpImg(), 0, 0);
}
$xeTable.closeTooltip();
},
handleRowDragSwapEvent(evnt, isSyncRow, dragRow, prevDragRow, prevDragPos, prevDragToChild) {
const { treeConfig, dragConfig } = props;
const rowDragOpts = computeRowDragOpts.value;
const { afterFullData, tableFullData, fullAllDataRowIdData } = internalData;
const $xeGanttView = internalData.xeGanttView;
const { animation, isPeerDrag, isCrossDrag, isSelfToChildDrag, dragEndMethod, dragToChildMethod } = rowDragOpts;
const treeOpts = computeTreeOpts.value;
const cellOpts = computeCellOpts.value;
const rowOpts = computeRowOpts.value;
const defaultRowHeight = computeDefaultRowHeight.value;
const { transform, rowField, mapChildrenField, parentField } = treeOpts;
const childrenField = treeOpts.children || treeOpts.childrenField;
const dEndMethod = dragEndMethod || (dragConfig ? dragConfig.dragEndMethod : null);
const dragOffsetIndex = prevDragPos === 'bottom' ? 1 : 0;
const el = refElem.value;
const errRest = {
status: false
};
if (!(el && prevDragRow && dragRow)) {
handleRowDragEndClearStatus();
return Promise.resolve(errRest);
}
// 判断是否有拖动
if (prevDragRow !== dragRow) {
const dragParams = {
oldRow: dragRow,
newRow: prevDragRow,
dragRow,
dragPos: prevDragPos,
dragToChild: !!prevDragToChild,
offsetIndex: dragOffsetIndex
};
const dragRowid = getRowid($xeTable, dragRow);
const dragRowRest = fullAllDataRowIdData[dragRowid] || {};
const _dragRowIndex = dragRowRest._index;
let dragRowHeight = 0;
let dragOffsetTop = -1;
if (animation) {
dragRowHeight = getCellRestHeight(dragRowRest, cellOpts, rowOpts, defaultRowHeight);
const oldTrEl = el.querySelector(`.vxe-body--row[rowid="${dragRowid}"]`);
if (oldTrEl) {
dragOffsetTop = oldTrEl.offsetTop;
}
}
let oafIndex = -1;
let nafIndex = -1;
const oldRest = dragRowRest;
const newRowid = getRowid($xeTable, prevDragRow);
const newRest = fullAllDataRowIdData[newRowid];
const oldAllMaps = {};
let isSelfToChildStatus = false;
// 如果为树结构
if (treeConfig) {
if (transform) {
if (oldRest && newRest) {
const { level: oldLevel } = oldRest;
const { level: newLevel } = newRest;
XEUtils.eachTree([dragRow], item => {
oldAllMaps[getRowid($xeTable, item)] = item;
}, { children: mapChildrenField });
if (oldLevel && newLevel) {
// 子到子
if (isPeerDrag && !isCrossDrag) {
if (oldRest.row[parentField] !== newRest.row[parentField]) {
// 非同级
handleRowDragEndClearStatus();
return Promise.resolve(errRest);
}
}
else {
if (!isCrossDrag) {
handleRowDragEndClearStatus();
return Promise.resolve(errRest);
}
if (oldAllMaps[newRowid]) {
isSelfToChildStatus = true;
if (!(isCrossDrag && isSelfToChildDrag)) {
if (VxeUI.modal) {
VxeUI.modal.message({
status: 'error',
content: getI18n('vxe.error.treeDragChild')
});
}
handleRowDragEndClearStatus();
return Promise.resolve(errRest);
}
}
}
}
else if (oldLevel) {
// 子到根
if (!isCrossDrag) {
handleRowDragEndClearStatus();
return Promise.resolve(errRest);
}
}
else if (newLevel) {
// 根到子
if (!isCrossDrag) {
handleRowDragEndClearStatus();
return Promise.resolve(errRest);
}
if (oldAllMaps[newRowid]) {
isSelfToChildStatus = true;
if (!(isCrossDrag && isSelfToChildDrag)) {
if (VxeUI.modal) {
VxeUI.modal.message({
status: 'error',
content: getI18n('vxe.error.treeDragChild')
});
}
handleRowDragEndClearStatus();
return Promise.resolve(errRest);
}
}
}
else {
// 根到根
}
}
}
}
const isDragToChildFlag = isSelfToChildDrag && dragToChildMethod ? dragToChildMethod(dragParams) : prevDragToChild;
if (dEndMethod) {
handleRowDragEndClearStatus();
}
return Promise.resolve(dEndMethod ? dEndMethod(dragParams) : true).then((status) => {
if (!status) {
return errRest;
}
// 如果为树结构
if (treeConfig) {
if (transform) {
// 移出源位置
if (oldRest && newRest) {
const fullList = XEUtils.toTreeArray(internalData.afterTreeFullData, {
updated: false,
key: rowField,
parentKey: parentField,
children: mapChildrenField
});
// 移出
const otfIndex = $xeTable.findRowIndexOf(fullList, dragRow);
fullList.splice(otfIndex, 1);
// 插入
const ptfIndex = $xeTable.findRowIndexOf(fullList, prevDragRow);
const ntfIndex = ptfIndex + dragOffsetIndex;
fullList.splice(ntfIndex, 0, dragRow);
// 改变层级
if (isSelfToChildStatus && (isCrossDrag && isSelfToChildDrag)) {
XEUtils.each(dragRow[childrenField], childRow => {
childRow[parentField] = dragRow[parentField];
});
}
dragRow[parentField] = isDragToChildFlag ? prevDragRow[rowField] : prevDragRow[parentField];
internalData.tableFullTreeData = XEUtils.toArrayTree(fullList, {
key: rowField,
parentKey: parentField,
children: childrenField,
mapChildren: mapChildrenField
});
}
}
}
else {
// 移出
oafIndex = $xeTable.findRowIndexOf(afterFullData, dragRow);
const otfIndex = $xeTable.findRowIndexOf(tableFullData, dragRow);
afterFullData.splice(oafIndex, 1);
tableFullData.splice(otfIndex, 1);
// 插入
const pafIndex = $xeTable.findRowIndexOf(afterFullData, prevDragRow);
const ptfIndex = $xeTable.findRowIndexOf(tableFullData, prevDragRow);
nafIndex = pafIndex + dragOffsetIndex;
const ntfIndex = ptfIndex + dragOffsetIndex;
afterFullData.splice(nafIndex, 0, dragRow);
tableFullData.splice(ntfIndex, 0, dragRow);
}
$xeTable.handleClearStack();
$xeTable.handleTableData(treeConfig && transform);
$xeTable.cacheRowMap(false);
updateScrollYStatus();
if (!(treeConfig && transform)) {
$xeTable.updateAfterDataIndex();
}
$xeTable.checkSelectionStatus();
if (reactData.scrollYLoad) {
$xeTable.updateScrollYSpace();
}
if (evnt) {
dispatchEvent('row-dragend', {
oldRow: dragRow,
newRow: prevDragRow,
dragRow,
dragPos: prevDragPos,
dragToChild: isDragToChildFlag,
offsetIndex: dragOffsetIndex,
_index: {
newIndex: nafIndex,
oldIndex: oafIndex
}
}, evnt);
}
return nextTick().then(() => {
if (animation) {
const { tableData } = reactData;
const { fullAllDataRowIdData } = internalData;
const dragRowRest = fullAllDataRowIdData[dragRowid];
const _newRowIndex = dragRowRest._index;
const firstRow = tableData[0];
const firstRowRest = fullAllDataRowIdData[getRowid($xeTable, firstRow)];
let wrapperEl = el;
if ($xeGantt && $xeGanttView) {
const { refGanttContainerElem } = $xeGantt.getRefMaps();
const ganttContainerElem = refGanttContainerElem.value;
if (ganttContainerElem) {
wrapperEl = ganttContainerElem;
}
}
if (firstRowRest) {
const _firstRowIndex = firstRowRest._index;
const _lastRowIndex = _firstRowIndex + tableData.length;
let rsIndex = -1;
let reIndex = -1;
let offsetRate = 1;
if (_dragRowIndex < _firstRowIndex) {
// 从上往下虚拟拖拽
rsIndex = 0;
reIndex = _newRowIndex - _firstRowIndex;
}
else if (_dragRowIndex > _lastRowIndex) {
// 从下往上虚拟拖拽
const $newRowIndex = dragRowRest.$index;
rsIndex = $newRowIndex + 1;
reIndex = tableData.length;
offsetRate = -1;
}
else {
if (_newRowIndex > _dragRowIndex) {
// 从上往下拖拽
rsIndex = _dragRowIndex - _firstRowIndex;
reIndex = rsIndex + _newRowIndex - _dragRowIndex;
}
else {
// 从下往上拖拽
rsIndex = _newRowIndex - _firstRowIndex;
reIndex = rsIndex + _dragRowIndex - _newRowIndex + 1;
offsetRate = -1;
}
}
const dragRangeList = tableData.slice(rsIndex, reIndex);
if (dragRangeList.length) {
const dtClss = [];
dragRangeList.forEach(row => {
const rowid = getRowid($xeTable, row);
dtClss.push(`.vxe-body--row[rowid="${rowid}"]`);
if ($xeGantt) {
dtClss.push(`.vxe-gantt-view--body-row[rowid="${rowid}"]`, `.vxe-gantt-view--chart-row[rowid="${rowid}"]`);
}
});
const dtTrList = wrapperEl.querySelectorAll(dtClss.join(','));
moveRowAnimateToTb(dtTrList, offsetRate * dragRowHeight);
}
}
const drClss = [`.vxe-body--row[rowid="${dragRowid}"]`];
if ($xeGantt) {
drClss.push(`.vxe-gantt-view--body-row[rowid="${dragRowid}"]`, `.vxe-gantt-view--chart-row[rowid="${dragRowid}"]`);
}
const newDtTrList = wrapperEl.querySelectorAll(drClss.join(','));
const newTrEl = newDtTrList[0];
if (dragOffsetTop > -1 && newTrEl) {
moveRowAnimateToTb(newDtTrList, dragOffsetTop - newTrEl.offsetTop);
}
}
updateRowOffsetTop();
updateRowExpandStyle();
$xeTable.updateCellAreas();
$xeTable.recalculate();
}).then(() => {
return {
status: true
};
});
}).catch(() => {
return errRest;
}).then((rest) => {
handleRowDragEndClearStatus();
return rest;
});
}
handleRowDragEndClearStatus();
return Promise.resolve(errRest);
},
handleCrossTableRowDragCancelEvent() {
handleRowDragEndClearStatus();
},
/**
* 处理跨表拖拽完成
*/
handleCrossTableRowDragFinishEvent(evnt) {
const { tableData } = reactData;
const { fullAllDataRowIdData } = internalData;
const rowOpts = computeRowOpts.value;
const cellOpts = computeCellOpts.value;
const defaultRowHeight = computeDefaultRowHeight.value;
const rowDragOpts = computeRowDragOpts.value;
const { animation, isCrossTableDrag } = rowDragOpts;
const treeOpts = computeTreeOpts.value;
const { mapChildrenField } = treeOpts;
const el = refElem.value;
if (isCrossTableDrag && crossTableDragRowObj && crossTableDragRowInfo) {
const { row: dragRow } = crossTableDragRowInfo;
if (dragRow) {
const dragRowid = getRowid($xeTable, dragRow);
const dragRowRest = fullAllDataRowIdData[dragRowid];
let dragRowHeight = 0;
let rsIndex = -1;
if (dragRowRest) {
if (animation) {
dragRowHeight = getCellRestHeight(dragRowRest, cellOpts, rowOpts, defaultRowHeight);
}
rsIndex = dragRowRest.$index;
}
const dragRangeList = rsIndex > -1 && rsIndex < tableData.length - 1 ? tableData.slice(rsIndex + 1) : [];
const dragList = XEUtils.toTreeArray([dragRow], {
updated: true,
children: mapChildrenField
});
$xeTable.remove(dragList).then(() => {
if (animation && dragRowHeight && dragRangeList.length) {
const $xeGanttView = internalData.xeGanttView;
let wrapperEl = el;
if ($xeGantt && $xeGanttView) {
const { refGanttContainerElem } = $xeGantt.getRefMaps();
const ganttContainerElem = refGanttContainerElem.value;
if (ganttContainerElem) {
wrapperEl = ganttContainerElem;
}
}
const dtClss = [];
dragRangeList.forEach(row => {
const rowid = getRowid($xeTable, row);
dtClss.push(`.vxe-body--row[rowid="${rowid}"]`);
if ($xeGantt) {
dtClss.push(`.vxe-gantt-view--body-row[rowid="${rowid}"]`, `.vxe-gantt-view--chart-row[rowid="${rowid}"]`);
}
});
const dtTrList = wrapperEl.querySelectorAll(dtClss.join(','));
moveRowAnimateToTb(dtTrList, dragRowHeight);
}
});
dispatchEvent('row-remove-dragend', {
row: dragRow
}, evnt);
handleRowDragEndClearStatus();
}
}
},
/**
* 处理跨表拖至新的空表
*/
handleCrossTableRowDragoverEmptyEvent(evnt) {
const { tableData } = reactData;
const rowDragOpts = computeRowDragOpts.value;
const { isCrossTableDrag } = rowDragOpts;
if (isCrossTableDrag && crossTableDragRowObj && !tableData.length) {
const { $oldTable, $newTable } = crossTableDragRowObj;
if ($oldTable) {
const oldTableReactData = $oldTable.reactData;
if ($oldTable.xID !== $xeTable.xID) {
if ($newTable && $newTable.xID !== $xeTable.xID) {
$newTable.hideCrossTableRowDropClearStatus();
}
evnt.preventDefault();
$oldTable.hideCrossTableRowDropClearStatus();
crossTableDragRowObj.$newTable = $xeTable;
internalData.prevDragRow = null;
reactData.dragTipText = oldTableReactData.dragTipText;
showDropTip(evnt, evnt.currentTarget, null, true, '');
}
}
}
},
/**
* 处理跨表拖插入
*/
handleCrossTableRowDragInsertEvent(evnt) {
const { treeConfig } = props;
const { prevDragRow, prevDragPos, prevDragToChild } = internalData;
const rowDragOpts = computeRowDragOpts.value;
const { animation, isSelfToChildDrag, isCrossTableDrag, dragEndMethod, dragToChildMethod } = rowDragOpts;
const rowOpts = computeRowOpts.value;
const cellOpts = computeCellOpts.value;
const defaultRowHeight = computeDefaultRowHeight.value;
const treeOpts = computeTreeOpts.value;
const { parentField, mapChildrenField } = treeOpts;
const childrenField = treeOpts.children || treeOpts.childrenField;
// 跨表拖拽
if (isCrossTableDrag && crossTableDragRowObj && crossTableDragRowInfo) {
const { row: oldRow } = crossTableDragRowInfo;
const { $oldTable } = crossTableDragRowObj;
const el = refElem.value;
if ($oldTable && oldRow) {
const dragRow = oldRow;
let dragOffsetIndex = -1;
if (prevDragRow) {
dragOffsetIndex = prevDragPos === 'bottom' ? 1 : 0;
}
const dragParams = {
oldRow: dragRow,
newRow: prevDragRow,
dragRow,
dragPos: prevDragPos,
dragToChild: !!prevDragToChild,
offsetIndex: dragOffsetIndex
};
const isDragToChildFlag = isSelfToChildDrag && dragToChildMethod ? dragToChildMethod(dragParams) : prevDragToChild;
const errRest = {
status: false
};
if (dragEndMethod) {
handleRowDragEndClearStatus();
}
Promise.resolve(dragEndMethod ? dragEndMethod(dragParams) : true).then((status) => {
if (!status) {
if ($oldTable) {
if ($oldTable.xID !== $xeTable.xID) {
$oldTable.handleCrossTableRowDragCancelEvent(evnt);
}
}
handleRowDragEndClearStatus();
return errRest;
}
let insertRest = Promise.resolve();
if (treeConfig) {
const dragList = XEUtils.toTreeArray([dragRow], {
updated: true,
children: mapChildrenField
});
$oldTable.handleCrossTableRowDragFinishEvent(evnt);
if (prevDragRow) {
dragRow[parentField] = prevDragRow[parentField];
}
else {
dragRow[parentField] = null;
}
dragList.forEach(row => {
row[childrenField] = undefined;
row[mapChildrenField] = undefined;
});
if (prevDragRow) {
if (prevDragPos === 'bottom') {
insertRest = $xeTable.insertNextAt(dragList, prevDragRow);
}
else {
insertRest = $xeTable.insertAt(dragList, prevDragRow);
}
}
else {
insertRest = $xeTable.insert(dragList);
}
}
else {
$oldTable.handleCrossTableRowDragFinishEvent(evnt);
if (prevDragRow) {
if (prevDragPos === 'bottom') {
insertRest = $xeTable.insertNextAt(dragRow, prevDragRow);
}
else {
insertRest = $xeTable.insertAt(dragRow, prevDragRow);
}
}
else {
insertRest = $xeTable.insert(dragRow);
}
}
dispatchEvent('row-insert-dragend', {
oldRow,
newRow: prevDragRow,
dragRow,
dragPos: prevDragPos,
dragToChild: isDragToChildFlag,
offsetIndex: dragOffsetIndex
}, evnt);
clearRowDragData();
insertRest.then(() => {
const { tableData } = reactData;
const { fullAllDataRowIdData } = internalData;
const oldRowid = getRowid($xeTable, dragRow);
const oldRowRest = fullAllDataRowIdData[oldRowid];
let dragRowHeight = 0;
let rsIndex = -1;
if (oldRowRest) {
if (animation) {
dragRowHeight = getCellRestHeight(oldRowRest, cellOpts, rowOpts, defaultRowHeight);
}
rsIndex = oldRowRest.$index;
}
const dragRangeList = rsIndex > -1 ? tableData.slice(rsIndex) : [];
if (animation && dragRowHeight && dragRangeList.length) {
const $xeGanttView = internalData.xeGanttView;
let wrapperEl = el;
if ($xeGantt && $xeGanttView) {
const { refGanttContainerElem } = $xeGantt.getRefMaps();
const ganttContainerElem = refGanttContainerElem.value;
if (ganttContainerElem) {
wrapperEl = ganttContainerElem;
}
}
const dtClss = [];
dragRangeList.forEach(row => {
const rowid = getRowid($xeTable, row);
dtClss.push(`.vxe-body--row[rowid="${rowid}"]`);
if ($xeGantt) {
dtClss.push(`.vxe-gantt-view--body-row[rowid="${rowid}"]`, `.vxe-gantt-view--chart-row[rowid="${rowid}"]`);
}
});
const dtTrList = wrapperEl.querySelectorAll(dtClss.join(','));
moveRowAnimateToTb(dtTrList, -dragRowHeight);
}
});
});
}
}
},
hideCrossTableRowDropClearStatus() {
hideDropTip();
},
handleRowDragDragendEvent(evnt) {
const { treeConfig } = props;
const { fullAllDataRowIdData, prevDragToChild } = internalData;
const { dragRow } = reactData;
const treeOpts = computeTreeOpts.value;
const { lazy } = treeOpts;
const hasChildField = treeOpts.hasChild || treeOpts.hasChildField;
const { prevDragRow, prevDragPos } = internalData;
const rowDragOpts = computeRowDragOpts.value;
const { isCrossTableDrag } = rowDragOpts;
// 跨表拖拽
if (isCrossTableDrag && crossTableDragRowObj) {
const { $newTable } = crossTableDragRowObj;
if ($newTable && $newTable.xID !== $xeTable.xID) {
$newTable.handleCrossTableRowDragInsertEvent(evnt);
return;
}
}
if (treeConfig && lazy && prevDragToChild) {
// 懒加载
const newRowid = getRowid($xeTable, prevDragRow);
const rowRest = fullAllDataRowIdData[newRowid];
if (prevDragRow[hasChildField]) {
if (rowRest && rowRest.treeLoaded) {
$xeTable.handleRowDragSwapEvent(evnt, true, dragRow, prevDragRow, prevDragPos, prevDragToChild);
}
}
else {
$xeTable.handleRowDragSwapEvent(evnt, true, dragRow, prevDragRow, prevDragPos, prevDragToChild);
}
}
else {
$xeTable.handleRowDragSwapEvent(evnt, true, dragRow, prevDragRow, prevDragPos, prevDragToChild);
}
},
handleRowDragDragoverEvent(evnt) {
const { treeConfig } = props;
const { fullAllDataRowIdData } = internalData;
const { dragRow } = reactData;
const treeOpts = computeTreeOpts.value;
const { lazy, transform, parentField } = treeOpts;
const hasChildField = treeOpts.hasChild || treeOpts.hasChildField;
const rowDragOpts = computeRowDragOpts.value;
const { isPeerDrag, isCrossDrag, isToChildDrag, isCrossTableDrag } = rowDragOpts;
if (!dragRow && !(isCrossTableDrag && (!treeConfig || isCrossDrag) && crossTableDragRowObj)) {
evnt.preventDefault();
return;
}
const isControlKey = hasControlKey(evnt);
const trEl = evnt.currentTarget;
const rowid = trEl.getAttribute('rowid') || '';
const rowRest = fullAllDataRowIdData[rowid];
if (rowRest) {
evnt.preventDefault();
const row = rowRest.row;
const offsetY = evnt.clientY - trEl.getBoundingClientRect().y;
const dragPos = offsetY < trEl.clientHeight / 2 ? 'top' : 'bottom';
internalData.prevDragToChild = !!(treeConfig && transform && (isCrossDrag && isToChildDrag) && isControlKey);
internalData.prevDragRow = row;
internalData.prevDragPos = dragPos;
// 跨表拖拽
if (isCrossTableDrag && (!treeConfig || isCrossDrag) && crossTableDragRowObj) {
const { $oldTable, $newTable } = crossTableDragRowObj;
if ($oldTable) {
const oldTableReactData = $oldTable.reactData;
if ($oldTable.xID === $xeTable.xID) {
if ($newTable) {
$newTable.hideCrossTableRowDropClearStatus();
}
reactData.isCrossDragRow = false;
oldTableReactData.isCrossDragRow = false;
crossTableDragRowObj.$newTable = null;
}
else {
if ($newTable && $newTable.xID !== $xeTable.xID) {
$newTable.hideCrossTableRowDropClearStatus();
}
$oldTable.hideCrossTableRowDropClearStatus();
oldTableReactData.isCrossDragRow = true;
reactData.dragTipText = oldTableReactData.dragTipText;
crossTableDragRowObj.$newTable = $xeTable;
showDropTip(evnt, trEl, null, true, dragPos);
return;
}
}
}
if ($xeTable.eqRow(dragRow, row) ||
(isControlKey && treeConfig && lazy && row[hasChildField] && rowRest && !rowRest.treeLoaded) ||
(!isCrossDrag && treeConfig && transform && (isPeerDrag ? dragRow[parentField] !== row[parentField] : rowRest.level))) {
showDropTip(evnt, trEl, null, false, dragPos);
return;
}
showDropTip(evnt, trEl, null, true, dragPos);
dispatchEvent('row-dragover', {
oldRow: dragRow,
targetRow: row,
dragPos
}, evnt);
}
},
handleCellDragMousedownEvent(evnt, params) {
var _a;
evnt.stopPropagation();
const { dragConfig } = props;
const rowDragOpts = computeRowDragOpts.value;
const { isCrossTableDrag, trigger, dragStartMethod } = rowDragOpts;
const { row } = params;
const dragEl = evnt.currentTarget;
const tdEl = trigger === 'cell' || trigger === 'row' ? dragEl : (_a = dragEl.parentElement) === null || _a === void 0 ? void 0 : _a.parentElement;
const trEl = tdEl.parentElement;
const dStartMethod = dragStartMethod || (dragConfig ? dragConfig.dragStartMethod : null);
clearRowDropOrigin();
if (dStartMethod && !dStartMethod(params)) {
trEl.draggable = false;
reactData.dragRow = null;
reactData.dragCol = null;
clearCrossTableDragStatus();
hideDropTip();
return;
}
if (isCrossTableDrag) {
crossTableDragRowInfo.row = row;
crossTableDragRowObj = { $oldTable: $xeTable, $newTable: null };
}
reactData.dragRow = row;
reactData.isCrossDragRow = false;
reactData.dragCol = null;
trEl.draggable = true;
updateRowDropOrigin(row);
updateRowDropTipContent(tdEl);
dispatchEvent('row-dragstart', params, evnt);
},
handleCellDragMouseupEvent() {
clearDragStatus();
},
/**
* 列拖拽
*/
handleHeaderCellDragDragstartEvent(evnt) {
if (evnt.dataTransfer) {
evnt.dataTransfer.setDragImage(getTpImg(), 0, 0);
}
$xeTable.closeTooltip();
},
handleColDragSwapColumn() {
handleUpdateColumn();
return parseColumns(false).then(() => {
$xeTable.updateCellAreas();
$xeTable.saveCustomStore('update:sort');
});
},
handleColDragSwapEvent(evnt, isSyncColumn, dragCol, prevDragCol, prevDragPos, prevDragToChild) {
const { mouseConfig } = props;
const columnDragOpts = computeColumnDragOpts.value;
const { animation, isPeerDrag, isCrossDrag, isSelfToChildDrag, isToChildDrag, dragEndMethod, dragToChildMethod } = columnDragOpts;
const { collectColumn, fullColumnIdData } = internalData;
const el = refElem.value;
const dragOffsetIndex = prevDragPos === 'right' ? 1 : 0;
const errRest = {
status: false
};
if (!(el && prevDragCol && dragCol)) {
return Promise.resolve(errRest);
}
// 判断是否有拖动
if (prevDragCol !== dragCol) {
const dragColumn = dragCol;
const newColumn = prevDragCol;
const dragParams = {
oldColumn: dragColumn,
newColumn,
dragColumn,
dragPos: prevDragPos,
dragToChild: !!prevDragToChild,
offsetIndex: dragOffsetIndex
};
let dragTargetColumn = null;
const dragAllTargetCols = [];
let dragColWidth = 0;
if (animation) {
XEUtils.eachTree([dragColumn], column => {
if (!dragTargetColumn && (!column.children || !column.children.length)) {
dragTargetColumn = column;
dragColWidth += column.renderWidth;
}
dragAllTargetCols.push(column);
});
}
if (!dragTargetColumn) {
dragTargetColumn = dragColumn;
}
const dragColRest = fullColumnIdData[dragTargetColumn.id] || {};
const _dragColIndex = dragColRest._index;
let dragOffsetLeft = -1;
if (animation) {
const oldTrEl = el.querySelector(`.vxe-table--column[colid="${dragTargetColumn.id}"]`);
if (oldTrEl) {
dragOffsetLeft = oldTrEl.offsetLeft;
}
}
let oafIndex = -1;
let nafIndex = -1;
const oldAllMaps = {};
XEUtils.eachTree([dragColumn], column => {
oldAllMaps[column.id] = column;
});
let isSelfToChildStatus = false;
if (dragColumn.parentId && newColumn.parentId) {
// 子到子
if (isPeerDrag && !isCrossDrag) {
if (dragColumn.parentId !== newColumn.parentId) {
// 非同级
handleColDragEndClearStatus();
return Promise.resolve(errRest);
}
}
else {
if (!isCrossDrag) {
handleColDragEndClearStatus();
return Promise.resolve(errRest);
}
if (oldAllMaps[newColumn.id]) {
isSelfToChildStatus = true;
if (!(isCrossDrag && isSelfToChildDrag)) {
if (VxeUI.modal) {
VxeUI.modal.message({
status: 'error',
content: getI18n('vxe.error.treeDragChild')
});
}
handleColDragEndClearStatus();
return Promise.resolve(errRest);
}
}
}
}
else if (dragColumn.parentId) {
// 子到根
if (!isCrossDrag) {
handleColDragEndClearStatus();
return Promise.resolve(errRest);
}
}
else if (newColumn.parentId) {
// 根到子
if (!isCrossDrag) {
handleColDragEndClearStatus();
return Promise.resolve(errRest);
}
if (oldAllMaps[newColumn.id]) {
isSelfToChildStatus = true;
if (!(isCrossDrag && isSelfToChildDrag)) {
if (VxeUI.modal) {
VxeUI.modal.message({
status: 'error',
content: getI18n('vxe.error.treeDragChild')
});
}
handleColDragEndClearStatus();
return Promise.resolve(errRest);
}
}
}
else {
// 根到根
}
const isDragToChildFlag = isSelfToChildDrag && dragToChildMethod ? dragToChildMethod(dragParams) : prevDragToChild;
return Promise.resolve(dragEndMethod ? dragEndMethod(dragParams) : true).then((status) => {
if (!status) {
return errRest;
}
const oldewMatchRest = XEUtils.findTree(collectColumn, item => item.id === dragColumn.id);
// 改变层级
if (isSelfToChildStatus && (isCrossDrag && isSelfToChildDrag)) {
if (oldewMatchRest) {
const { items: oCols, index: oIndex } = oldewMatchRest;
const childList = dragColumn.children || [];
childList.forEach(column => {
column.parentId = dragColumn.parentId;
});
oCols.splice(oIndex, 1, ...childList);
dragColumn.children = [];
}
}
else {
if (oldewMatchRest) {
const { items: oCols, index: oIndex, parent: oParent } = oldewMatchRest;
oCols.splice(oIndex, 1);
if (!oParent) {
oafIndex = oIndex;
}
}
}
const newMatchRest = XEUtils.findTree(collectColumn, item => item.id === newColumn.id);
if (newMatchRest) {
const { items: nCols, index: nIndex, parent: nParent } = newMatchRest;
// 转子级
if ((isCrossDrag && isToChildDrag) && isDragToChildFlag) {
dragColumn.parentId = newColumn.id;
newColumn.children = (newColumn.children || []).concat([dragColumn]);
}
else {
dragColumn.parentId = newColumn.parentId;
nCols.splice(nIndex + dragOffsetIndex, 0, dragColumn);
}
if (!nParent) {
nafIndex = nIndex;
}
}
XEUtils.eachTree(collectColumn, (column, index, items, path, parentColumn) => {
if (!parentColumn) {
const sortIndex = index + 1;
column.renderSortNumber = sortIndex;
}
});
$xeTable.handleClearStack();
if (mouseConfig) {
if ($xeTable.clearSelected) {
$xeTable.clearSelected();
}
if ($xeTable.clearCellAreas) {
$xeTable.clearCellAreas();
$xeTable.clearCopyCellArea();
}
}
if (evnt) {
dispatchEvent('column-dragend', {
oldColumn: dragColumn,
newColumn,
dragColumn,
dragPos: prevDragPos,
dragToChild: isDragToChildFlag,
offsetIndex: dragOffsetIndex,
_index: {
newIndex: nafIndex,
oldIndex: oafIndex
}
}, evnt);
}
return nextTick().then(() => {
if (isSyncColumn) {
return $xeTable.handleColDragSwapColumn();
}
}).then(() => {
if (animation) {
const { tableColumn } = reactData;
const { visibleColumn, fullColumnIdData } = internalData;
let dragNewColumn = null;
const dragNewColMaps = {};
XEUtils.eachTree([dragColumn], column => {
if (!dragNewColumn && (!column.children || !column.children.length)) {
dragNewColumn = column;
}
dragNewColMaps[column.id] = column;
});
if (!dragNewColumn) {
dragNewColumn = dragColumn;
}
if (dragColWidth && dragAllTargetCols.length) {
const _newColIndex = XEUtils.findIndexOf(visibleColumn, column => !!dragNewColumn && column.id === dragNewColumn.id);
const firstCol = tableColumn[0];
const firstColRest = fullColumnIdData[firstCol.id];
if (firstColRest) {
const _firstColIndex = firstColRest._index;
const _lastColIndex = _firstColIndex + tableColumn.length;
let csIndex = -1;
let ceIndex = -1;
let offsetRate = 1;
if (_dragColIndex < _firstColIndex) {
// 从左往右虚拟拖拽
csIndex = 0;
ceIndex = _newColIndex - _firstColIndex;
}
else if (_dragColIndex > _lastColIndex) {
// 从右往左虚拟拖拽
const $newRowIndex = dragColRest.$index;
csIndex = $newRowIndex + 1;
ceIndex = tableColumn.length;
offsetRate = -1;
}
else {
if (_newColIndex > _dragColIndex) {
// 从左往右拖拽
csIndex = _dragColIndex - _firstColIndex;
ceIndex = csIndex + _newColIndex - _dragColIndex;
}
else {
// 从右往左拖拽
csIndex = _newColIndex - _firstColIndex + 1;
ceIndex = csIndex + _dragColIndex - _newColIndex;
offsetRate = -1;
}
}
const dragRangeList = [];
const dragRangeMaps = {};
for (let i = csIndex; i < ceIndex; i++) {
const column = tableColumn[i];
if (!dragRangeMaps[column.id] && !dragNewColMaps[column.id]) {
dragRangeMaps[column.id] = column;
dragRangeList.push(column);
}
}
XEUtils.eachTree([newColumn], column => {
if (!dragRangeMaps[column.id]) {
dragRangeMaps[column.id] = column;
dragRangeList.push(column);
}
});
if (dragRangeList.length) {
const dtTrList = el.querySelectorAll(dragRangeList.map(column => `.vxe-table--column[colid="${column.id}"]`).join(','));
moveColAnimateToLr(dtTrList, offsetRate * dragColWidth);
}
}
const newTrList = el.querySelectorAll(dragAllTargetCols.map(column => `.vxe-table--column[colid="${column.id}"]`).join(','));
const newTdEl = newTrList[0];
if (dragOffsetLeft > -1 && newTdEl) {
moveColAnimateToLr(newTrList, dragOffsetLeft - newTdEl.offsetLeft);
}
}
}
updateColumnOffsetLeft();
loadScrollXData();
$xeTable.updateCellAreas();
return {
status: true
};
});
}).catch(() => {
return errRest;
}).then((rest) => {
handleColDragEndClearStatus();
return rest;
});
}
handleColDragEndClearStatus();
return Promise.resolve(errRest);
},
handleHeaderCellDragDragendEvent(evnt) {
const { dragCol } = reactData;
const { prevDragCol, prevDragPos, prevDragToChild } = internalData;
$xeTable.handleColDragSwapEvent(evnt, true, dragCol, prevDragCol, prevDragPos, prevDragToChild);
},
handleHeaderCellDragDragoverEvent(evnt) {
const { dragCol } = reactData;
const columnDragOpts = computeColumnDragOpts.value;
const { isToChildDrag, isPeerDrag, isCrossDrag } = columnDragOpts;
if (!dragCol) {
evnt.preventDefault();
return;
}
const isControlKey = hasControlKey(evnt);
const thEl = evnt.currentTarget;
const colid = thEl.getAttribute('colid');
const column = $xeTable.getColumnById(colid);
if (column) {
evnt.preventDefault();
const { clientX } = evnt;
const offsetX = clientX - thEl.getBoundingClientRect().x;
const dragPos = offsetX < thEl.clientWidth / 2 ? 'left' : 'right';
internalData.prevDragToChild = !!((isCrossDrag && isToChildDrag) && isControlKey);
internalData.prevDragCol = column;
internalData.prevDragPos = dragPos;
if (column.fixed ||
(dragCol && dragCol.id === column.id) ||
(!isCrossDrag && (isPeerDrag ? dragCol.parentId !== column.parentId : column.parentId))) {
showDropTip(evnt, null, thEl, false, dragPos);
return;
}
showDropTip(evnt, null, thEl, true, dragPos);
dispatchEvent('column-dragover', {
oldColumn: dragCol,
targetColumn: column,
dragPos
}, evnt);
// 边缘滚动
const el = refElem.value;
if (!el) {
return;
}
const xHandleEl = refScrollXHandleElem.value;
const tableBody = refTableBody.value;
const tableBodyElem = tableBody ? tableBody.$el : null;
const scrollTargetEl = xHandleEl || tableBodyElem;
if (scrollTargetEl) {
const wrapperRect = el.getBoundingClientRect();
const tableWrapperWidth = el.clientWidth;
const leftContainerElem = refLeftContainer.value;
const leftContainerWidth = leftContainerElem ? leftContainerElem.clientWidth : 0;
const rightContainerElem = refRightContainer.value;
const rightContainerWidth = rightContainerElem ? rightContainerElem.clientWidth : 0;
const srartX = wrapperRect.x + leftContainerWidth;
const endX = wrapperRect.x + tableWrapperWidth - rightContainerWidth;
const distSize = 28;
const startDistSize = clientX - srartX;
const endDistSize = endX - clientX;
if (startDistSize > 0 && startDistSize <= distSize) {
const scrollRatio = Math.floor(tableWrapperWidth / (startDistSize > distSize / 2 ? 240 : 120));
scrollTargetEl.scrollLeft -= scrollRatio * (distSize - startDistSize);
}
else if (endDistSize > 0 && endDistSize <= distSize) {
const scrollRatio = Math.floor(tableWrapperWidth / (endDistSize > distSize / 2 ? 240 : 120));
scrollTargetEl.scrollLeft += scrollRatio * (distSize - endDistSize);
}
}
}
},
handleHeaderCellDragMousedownEvent(evnt, params) {
var _a;
evnt.stopPropagation();
const columnDragOpts = computeColumnDragOpts.value;
const { trigger, dragStartMethod } = columnDragOpts;
const { column } = params;
const dragEl = evnt.currentTarget;
const thEl = trigger === 'cell' ? dragEl : (_a = dragEl.parentElement) === null || _a === void 0 ? void 0 : _a.parentElement;
clearColDropOrigin();
if (dragStartMethod && !dragStartMethod(params)) {
thEl.draggable = false;
reactData.dragRow = null;
reactData.dragCol = null;
clearCrossTableDragStatus();
hideDropTip();
return;
}
reactData.dragCol = column;
reactData.dragRow = null;
thEl.draggable = true;
clearCrossTableDragStatus();
updateColDropOrigin(column);
updateColDropTipContent(thEl);
dispatchEvent('column-dragstart', params, evnt);
},
handleHeaderCellDragMouseupEvent() {
clearColDropOrigin();
hideDropTip();
clearCrossTableDragStatus();
reactData.dragRow = null;
reactData.dragCol = null;
},
handleScrollEvent(evnt, isRollY, isRollX, scrollTop, scrollLeft, params) {
const { highlightHoverRow } = props;
const { lastScrollLeft, lastScrollTop } = internalData;
const xHandleEl = refScrollXHandleElem.value;
const yHandleEl = refScrollYHandleElem.value;
if (!xHandleEl || !yHandleEl) {
return;
}
const rowOpts = computeRowOpts.value;
const validTip = refValidTooltip.value;
const tooltip = refTooltip.value;
const bodyHeight = yHandleEl.clientHeight;
const bodyWidth = xHandleEl.clientWidth;
const scrollHeight = yHandleEl.scrollHeight;
const scrollWidth = xHandleEl.scrollWidth;
let isTop = false;
let isBottom = false;
let isLeft = false;
let isRight = false;
let direction = '';
let isTopBoundary = false;
let isBottomBoundary = false;
let isLeftBoundary = false;
let isRightBoundary = false;
if (isRollX) {
const xThreshold = computeScrollXThreshold.value;
isLeft = scrollLeft <= 0;
if (!isLeft) {
isRight = scrollLeft + bodyWidth >= scrollWidth;
}
if (scrollLeft > lastScrollLeft) {
direction = 'right';
if (scrollLeft + bodyWidth >= scrollWidth - xThreshold) {
isRightBoundary = true;
}
}
else {
direction = 'left';
if (scrollLeft <= xThreshold) {
isLeftBoundary = true;
}
}
$xeTable.checkScrolling();
internalData.lastScrollLeft = scrollLeft;
}
if (isRollY) {
const yThreshold = computeScrollYThreshold.value;
isTop = scrollTop <= 1;
if (!isTop) {
isBottom = scrollTop + bodyHeight >= scrollHeight - 1;
}
if (scrollTop > lastScrollTop) {
direction = 'bottom';
if (scrollTop + bodyHeight >= scrollHeight - yThreshold) {
isBottomBoundary = true;
}
}
else {
direction = 'top';
if (scrollTop <= yThreshold) {
isTopBoundary = true;
}
}
internalData.lastScrollTop = scrollTop;
}
internalData.lastSTime = Date.now();
const evntParams = Object.assign({ source: sourceType, scrollTop,
scrollLeft,
bodyHeight,
bodyWidth,
scrollHeight,
scrollWidth, isX: isRollX, isY: isRollY, isTop,
isBottom,
isLeft,
isRight,
direction }, params);
updateRowExpandStyle();
checkLastSyncScroll(isRollX, isRollY);
if (isRollX) {
$xeTable.closeFilter();
}
if (rowOpts.isHover || highlightHoverRow) {
$xeTable.clearHoverRow();
}
if (validTip && validTip.reactData.visible) {
validTip.close();
}
if (tooltip && tooltip.reactData.visible) {
tooltip.close();
}
if (isBottomBoundary || isTopBoundary || isRightBoundary || isLeftBoundary) {
dispatchEvent('scroll-boundary', evntParams, evnt);
}
dispatchEvent('scroll', evntParams, evnt);
},
/**
* 横向 X 可视渲染事件处理
*/
triggerScrollXEvent() {
const virtualXOpts = computeVirtualXOpts.value;
if (virtualXOpts.immediate) {
loadScrollXData();
}
else {
lazyScrollXData();
}
},
/**
* 纵向 Y 可视渲染事件处理
*/
triggerScrollYEvent() {
const virtualYOpts = computeVirtualYOpts.value;
if (virtualYOpts.immediate) {
loadScrollYData();
}
else {
lazyScrollYData();
}
},
triggerBodyScrollEvent(evnt, fixedType) {
const { scrollYLoad, scrollXLoad } = reactData;
const { elemStore, intoRunScroll, lastScrollTop, lastScrollLeft, inWheelScroll, inVirtualScroll, inHeaderScroll, inBodyScroll, scrollRenderType, inFooterScroll } = internalData;
if (inWheelScroll || inVirtualScroll || inHeaderScroll || inFooterScroll) {
return;
}
const xHandleEl = refScrollXHandleElem.value;
const yHandleEl = refScrollYHandleElem.value;
const leftScrollElem = getRefElem(elemStore['left-body-scroll']);
const bodyScrollElem = getRefElem(elemStore['main-body-scroll']);
const rightScrollElem = getRefElem(elemStore['right-body-scroll']);
const headerScrollElem = getRefElem(elemStore['main-header-scroll']);
const footerScrollElem = getRefElem(elemStore['main-footer-scroll']);
const rowExpandEl = refRowExpandElem.value;
if (intoRunScroll) {
return;
}
if (!bodyScrollElem) {
return;
}
if (!xHandleEl) {
return;
}
if (!yHandleEl) {
return;
}
if (inBodyScroll) {
if (scrollRenderType !== fixedType) {
return;
}
}
let scrollTop = yHandleEl.scrollTop;
let scrollLeft = xHandleEl.scrollLeft;
if (leftScrollElem && fixedType === 'left') {
scrollTop = leftScrollElem.scrollTop;
}
else if (rightScrollElem && fixedType === 'right') {
scrollTop = rightScrollElem.scrollTop;
}
else {
scrollTop = bodyScrollElem.scrollTop;
scrollLeft = bodyScrollElem.scrollLeft;
}
const isRollX = scrollLeft !== lastScrollLeft;
const isRollY = scrollTop !== lastScrollTop;
internalData.inBodyScroll = true;
internalData.scrollRenderType = fixedType;
if (isRollY) {
if (fixedType === 'left') {
setScrollTop(bodyScrollElem, scrollTop);
setScrollTop(rightScrollElem, scrollTop);
}
else if (fixedType === 'right') {
setScrollTop(bodyScrollElem, scrollTop);
setScrollTop(leftScrollElem, scrollTop);
}
else {
setScrollTop(leftScrollElem, scrollTop);
setScrollTop(rightScrollElem, scrollTop);
}
setScrollTop(yHandleEl, scrollTop);
setScrollTop(rowExpandEl, scrollTop);
syncGanttScrollTop(scrollTop);
if (scrollYLoad) {
$xeTable.triggerScrollYEvent(evnt);
}
}
if (isRollX) {
setScrollLeft(xHandleEl, scrollLeft);
setScrollLeft(headerScrollElem, scrollLeft);
setScrollLeft(footerScrollElem, scrollLeft);
if (scrollXLoad) {
$xeTable.triggerScrollXEvent(evnt);
}
}
$xeTable.handleScrollEvent(evnt, isRollY, isRollX, scrollTop, scrollLeft, {
type: 'body',
fixed: fixedType
});
},
triggerHeaderScrollEvent(evnt, fixedType) {
const { scrollXLoad } = reactData;
const { elemStore, intoRunScroll, inWheelScroll, inVirtualScroll, inBodyScroll, inFooterScroll } = internalData;
if (inWheelScroll || inVirtualScroll || inBodyScroll || inFooterScroll) {
return;
}
const yHandleEl = refScrollYHandleElem.value;
const xHandleEl = refScrollXHandleElem.value;
const bodyScrollElem = getRefElem(elemStore['main-body-scroll']);
const headerScrollElem = getRefElem(elemStore['main-header-scroll']);
const footerScrollElem = getRefElem(elemStore['main-footer-scroll']);
if (intoRunScroll) {
return;
}
if (!headerScrollElem) {
return;
}
if (!xHandleEl) {
return;
}
if (!yHandleEl) {
return;
}
const scrollTop = yHandleEl.scrollTop;
const scrollLeft = headerScrollElem.scrollLeft;
const isRollX = true;
const isRollY = false;
internalData.inHeaderScroll = true;
setScrollLeft(xHandleEl, scrollLeft);
setScrollLeft(footerScrollElem, scrollLeft);
setScrollLeft(bodyScrollElem, scrollLeft);
if (scrollXLoad) {
$xeTable.triggerScrollXEvent(evnt);
}
$xeTable.handleScrollEvent(evnt, isRollY, isRollX, scrollTop, scrollLeft, {
type: 'header',
fixed: fixedType
});
},
triggerFooterScrollEvent(evnt, fixedType) {
const { scrollXLoad } = reactData;
const { elemStore, intoRunScroll, inWheelScroll, inVirtualScroll, inHeaderScroll, inBodyScroll } = internalData;
if (inWheelScroll || inVirtualScroll || inHeaderScroll || inBodyScroll) {
return;
}
const yHandleEl = refScrollYHandleElem.value;
const xHandleEl = refScrollXHandleElem.value;
const bodyScrollElem = getRefElem(elemStore['main-body-scroll']);
const headerScrollElem = getRefElem(elemStore['main-header-scroll']);
const footerScrollElem = getRefElem(elemStore['main-footer-scroll']);
if (intoRunScroll) {
return;
}
if (!footerScrollElem) {
return;
}
if (!xHandleEl) {
return;
}
if (!yHandleEl) {
return;
}
const scrollTop = yHandleEl.scrollTop;
const scrollLeft = footerScrollElem.scrollLeft;
const isRollX = true;
const isRollY = false;
internalData.inFooterScroll = true;
setScrollLeft(xHandleEl, scrollLeft);
setScrollLeft(headerScrollElem, scrollLeft);
setScrollLeft(bodyScrollElem, scrollLeft);
if (scrollXLoad) {
$xeTable.triggerScrollXEvent(evnt);
}
$xeTable.handleScrollEvent(evnt, isRollY, isRollX, scrollTop, scrollLeft, {
type: 'footer',
fixed: fixedType
});
},
triggerBodyWheelEvent(evnt) {
const { target, deltaY, deltaX, shiftKey } = evnt;
if (target && /^textarea$/i.test(target.tagName)) {
return;
}
// 如果滚轮未移动或者触摸板未变化位置
if (!deltaY && !deltaX) {
return;
}
const { highlightHoverRow } = tableProps;
const { scrollXLoad, scrollYLoad, overflowX, overflowY, expandColumn } = reactData;
const leftFixedWidth = computeLeftFixedWidth.value;
const rightFixedWidth = computeRightFixedWidth.value;
const { elemStore, lastScrollTop, lastScrollLeft } = internalData;
const rowOpts = computeRowOpts.value;
const scrollbarXOpts = computeScrollbarXOpts.value;
const scrollbarYOpts = computeScrollbarYOpts.value;
const xHandleEl = refScrollXHandleElem.value;
const yHandleEl = refScrollYHandleElem.value;
const leftScrollElem = getRefElem(elemStore['left-body-scroll']);
const headerScrollElem = getRefElem(elemStore['main-header-scroll']);
const bodyScrollElem = getRefElem(elemStore['main-body-scroll']);
const footerScrollElem = getRefElem(elemStore['main-footer-scroll']);
const rightScrollElem = getRefElem(elemStore['right-body-scroll']);
const rowExpandEl = refRowExpandElem.value;
if (!bodyScrollElem) {
return;
}
const wheelSpeed = getWheelSpeed(internalData.lastSTime);
const deltaTop = shiftKey ? 0 : (deltaY * wheelSpeed);
const deltaLeft = (shiftKey ? (deltaX || deltaY) : deltaX) * wheelSpeed;
const currScrollTop = bodyScrollElem.scrollTop;
const currScrollLeft = bodyScrollElem.scrollLeft;
const scrollTop = Math.max(0, currScrollTop + deltaTop);
const scrollLeft = Math.max(0, currScrollLeft + deltaLeft);
const isRollX = overflowX && scrollLeft !== lastScrollLeft;
const isRollY = overflowY && scrollTop !== lastScrollTop;
if (isRollX) {
// 如果禁用滚动
if (scrollbarXOpts.visible === 'hidden') {
evnt.preventDefault();
return;
}
}
if (isRollY) {
// 如果禁用滚动
if (scrollbarYOpts.visible === 'hidden') {
evnt.preventDefault();
return;
}
const isTopWheel = deltaTop < 0;
// 如果滚动位置已经是顶部或底部,则不需要触发
if (isTopWheel ? currScrollTop <= 0 : currScrollTop >= bodyScrollElem.scrollHeight - bodyScrollElem.clientHeight) {
return;
}
}
// 展开行处理,如果展开行嵌入表格中
if ($xeParentTable) {
if (isRollY) {
if (checkTargetElement(evnt.target, [leftScrollElem, bodyScrollElem, rightScrollElem], evnt.currentTarget)) {
evnt.stopPropagation();
return;
}
}
if (isRollX) {
if (checkTargetElement(evnt.target, [headerScrollElem, bodyScrollElem, footerScrollElem], evnt.currentTarget)) {
evnt.stopPropagation();
return;
}
}
}
if (!(isRollX || leftFixedWidth || rightFixedWidth || expandColumn)) {
return;
}
if (rowOpts.isHover || highlightHoverRow) {
$xeTable.clearHoverRow();
}
// 用于鼠标纵向滚轮处理
if (isRollX) {
evnt.preventDefault();
internalData.inWheelScroll = true;
wheelScrollLeftTo(scrollLeft, (offsetLeft) => {
internalData.inWheelScroll = true;
const currLeftNum = offsetLeft;
setScrollLeft(xHandleEl, currLeftNum);
setScrollLeft(bodyScrollElem, currLeftNum);
setScrollLeft(headerScrollElem, currLeftNum);
setScrollLeft(footerScrollElem, currLeftNum);
if (scrollXLoad) {
$xeTable.triggerScrollXEvent(evnt);
}
$xeTable.handleScrollEvent(evnt, isRollY, isRollX, bodyScrollElem.scrollTop, currLeftNum, {
type: 'table',
fixed: ''
});
});
}
if (isRollY) {
evnt.preventDefault();
internalData.inWheelScroll = true;
wheelScrollTopTo(scrollTop, (offsetTop) => {
internalData.inWheelScroll = true;
const currTopNum = offsetTop;
setScrollTop(yHandleEl, currTopNum);
setScrollTop(bodyScrollElem, currTopNum);
setScrollTop(leftScrollElem, currTopNum);
setScrollTop(rightScrollElem, currTopNum);
setScrollTop(rowExpandEl, currTopNum);
syncGanttScrollTop(currTopNum);
if (scrollYLoad) {
$xeTable.triggerScrollYEvent(evnt);
}
$xeTable.handleScrollEvent(evnt, isRollY, isRollX, offsetTop, bodyScrollElem.scrollLeft, {
type: 'table',
fixed: ''
});
});
}
},
triggerVirtualScrollXEvent(evnt) {
const { scrollXLoad } = reactData;
const { elemStore, inWheelScroll, lastScrollTop, inHeaderScroll, inBodyScroll, inFooterScroll } = internalData;
if (inHeaderScroll || inBodyScroll || inFooterScroll) {
return;
}
if (inWheelScroll) {
return;
}
const headerScrollElem = getRefElem(elemStore['main-header-scroll']);
const bodyScrollElem = getRefElem(elemStore['main-body-scroll']);
const footerScrollElem = getRefElem(elemStore['main-footer-scroll']);
const yHandleEl = refScrollYHandleElem.value;
const wrapperEl = evnt.currentTarget;
const { scrollLeft } = wrapperEl;
const yBodyEl = yHandleEl || bodyScrollElem;
let scrollTop = 0;
if (yBodyEl) {
scrollTop = yBodyEl.scrollTop;
}
const isRollX = true;
const isRollY = scrollTop !== lastScrollTop;
internalData.inVirtualScroll = true;
setScrollLeft(bodyScrollElem, scrollLeft);
setScrollLeft(headerScrollElem, scrollLeft);
setScrollLeft(footerScrollElem, scrollLeft);
if (scrollXLoad) {
$xeTable.triggerScrollXEvent(evnt);
}
$xeTable.handleScrollEvent(evnt, isRollY, isRollX, scrollTop, scrollLeft, {
type: 'table',
fixed: ''
});
},
triggerVirtualScrollYEvent(evnt) {
const { scrollYLoad } = reactData;
const { elemStore, inWheelScroll, lastScrollLeft, inHeaderScroll, inBodyScroll, inFooterScroll } = internalData;
if (inHeaderScroll || inBodyScroll || inFooterScroll) {
return;
}
if (inWheelScroll) {
return;
}
const leftScrollElem = getRefElem(elemStore['left-body-scroll']);
const bodyScrollElem = getRefElem(elemStore['main-body-scroll']);
const rightScrollElem = getRefElem(elemStore['right-body-scroll']);
const rowExpandEl = refRowExpandElem.value;
const xHandleEl = refScrollXHandleElem.value;
const wrapperEl = evnt.currentTarget;
const { scrollTop } = wrapperEl;
const xBodyEl = xHandleEl || bodyScrollElem;
let scrollLeft = 0;
if (xBodyEl) {
scrollLeft = xBodyEl.scrollLeft;
}
const isRollX = scrollLeft !== lastScrollLeft;
const isRollY = true;
internalData.inVirtualScroll = true;
setScrollTop(bodyScrollElem, scrollTop);
setScrollTop(leftScrollElem, scrollTop);
setScrollTop(rightScrollElem, scrollTop);
setScrollTop(rowExpandEl, scrollTop);
syncGanttScrollTop(scrollTop);
if (scrollYLoad) {
$xeTable.triggerScrollYEvent(evnt);
}
$xeTable.handleScrollEvent(evnt, isRollY, isRollX, scrollTop, scrollLeft, {
type: 'table',
fixed: ''
});
},
/**
* 对于树形结构中,可以直接滚动到指定深层节点中
* 对于某些特定的场景可能会用到,比如定位到某一节点
* @param {Row} row 行对象
*/
scrollToTreeRow(row) {
const { treeConfig } = props;
const { isRowGroupStatus } = reactData;
const { tableFullData } = internalData;
const rests = [];
if (treeConfig || isRowGroupStatus) {
const aggregateOpts = computeAggregateOpts.value;
const treeOpts = computeTreeOpts.value;
const childrenField = treeOpts.children || treeOpts.childrenField;
const matchObj = XEUtils.findTree(tableFullData, item => $xeTable.eqRow(item, row), { children: isRowGroupStatus ? aggregateOpts.mapChildrenField : childrenField });
if (matchObj) {
const nodes = matchObj.nodes;
nodes.forEach((row, index) => {
if (index < nodes.length - 1 && !$xeTable.isTreeExpandByRow(row)) {
rests.push($xeTable.setTreeExpand(row, true));
}
});
}
}
return Promise.all(rests).then(() => rowToVisible($xeTable, row));
},
updateScrollYStatus,
// 更新横向 X 可视渲染上下剩余空间大小
updateScrollXSpace() {
const { scrollXLoad, overflowX, scrollXWidth } = reactData;
const { visibleColumn, scrollXStore, elemStore, fullColumnIdData } = internalData;
const $xeGanttView = internalData.xeGanttView;
const mouseOpts = computeMouseOpts.value;
const tableBody = refTableBody.value;
const tableBodyElem = tableBody ? tableBody.$el : null;
if (tableBodyElem) {
const bodyScrollElem = getRefElem(elemStore['main-body-scroll']);
const bodyTableElem = getRefElem(elemStore['main-body-table']);
const headerTableElem = getRefElem(elemStore['main-header-table']);
const footerTableElem = getRefElem(elemStore['main-footer-table']);
let xSpaceLeft = 0;
const firstColumn = visibleColumn[scrollXStore.startIndex];
if (firstColumn) {
const colRest = fullColumnIdData[firstColumn.id] || {};
xSpaceLeft = colRest.oLeft;
}
let clientWidth = 0;
if (bodyScrollElem) {
clientWidth = bodyScrollElem.clientWidth;
}
// 虚拟渲染
let isScrollXBig = false;
let ySpaceWidth = scrollXWidth;
if (scrollXWidth > maxXWidth) {
// 触右
if (bodyScrollElem && bodyTableElem && bodyScrollElem.scrollLeft + clientWidth >= maxXWidth) {
xSpaceLeft = maxXWidth - bodyTableElem.clientWidth;
}
else {
xSpaceLeft = (maxXWidth - clientWidth) * (xSpaceLeft / (scrollXWidth - clientWidth));
}
ySpaceWidth = maxXWidth;
isScrollXBig = true;
}
if (!(scrollXLoad && overflowX)) {
xSpaceLeft = 0;
}
if (getConfig().scrollMarginStyle) {
// 已废弃方式
if (headerTableElem) {
headerTableElem.style.marginLeft = headerTableElem.getAttribute('xvm') ? `${xSpaceLeft}px` : '';
}
if (bodyTableElem) {
bodyTableElem.style.marginLeft = `${xSpaceLeft}px`;
}
if (footerTableElem) {
footerTableElem.style.marginLeft = footerTableElem.getAttribute('xvm') ? `${xSpaceLeft}px` : '';
}
}
else {
if (headerTableElem) {
headerTableElem.style.transform = headerTableElem.getAttribute('xvm') ? `translate(${xSpaceLeft}px, 0px)` : '';
}
if (bodyTableElem) {
bodyTableElem.style.transform = `translate(${xSpaceLeft}px, ${reactData.scrollYTop || 0}px)`;
}
if (footerTableElem) {
footerTableElem.style.transform = footerTableElem.getAttribute('xvm') ? `translate(${xSpaceLeft}px, 0px)` : '';
}
}
const containerList = ['main'];
containerList.forEach(name => {
const layoutList = ['header', 'body', 'footer'];
layoutList.forEach(layout => {
const xSpaceElem = getRefElem(elemStore[`${name}-${layout}-xSpace`]);
if (xSpaceElem) {
xSpaceElem.style.width = scrollXLoad ? `${ySpaceWidth}px` : '';
}
});
});
reactData.scrollXLeft = xSpaceLeft;
reactData.scrollXWidth = ySpaceWidth;
reactData.isScrollXBig = isScrollXBig;
const scrollXSpaceEl = refScrollXSpaceElem.value;
if (scrollXSpaceEl) {
scrollXSpaceEl.style.width = `${ySpaceWidth}px`;
}
calcScrollbar();
if (isScrollXBig && mouseOpts.area) {
errLog('vxe.error.notProp', ['mouse-config.area']);
}
if ($xeGanttView && $xeGanttView.handleUpdateSXSpace) {
$xeGanttView.handleUpdateSXSpace();
}
return nextTick().then(() => {
updateStyle();
});
}
},
// 更新纵向 Y 可视渲染上下剩余空间大小
updateScrollYSpace() {
const { isAllOverflow, overflowY, scrollYLoad, scrollYHeight, expandColumn } = reactData;
const { scrollYStore, elemStore, isResizeCellHeight, afterFullData, fullAllDataRowIdData, rowExpandedMaps } = internalData;
const $xeGanttView = internalData.xeGanttView;
const { startIndex } = scrollYStore;
const mouseOpts = computeMouseOpts.value;
const expandOpts = computeExpandOpts.value;
const rowOpts = computeRowOpts.value;
const cellOpts = computeCellOpts.value;
const defaultRowHeight = computeDefaultRowHeight.value;
const bodyScrollElem = getRefElem(elemStore['main-body-scroll']);
const bodyTableElem = getRefElem(elemStore['main-body-table']);
const leftBodyTableElem = getRefElem(elemStore['left-body-table']);
const rightbodyTableElem = getRefElem(elemStore['right-body-table']);
const containerList = ['main', 'left', 'right'];
let ySpaceTop = 0;
let sYHeight = scrollYHeight;
let isScrollYBig = false;
if (scrollYLoad) {
const isCustomCellHeight = isResizeCellHeight || cellOpts.height || rowOpts.height;
if (!isCustomCellHeight && !expandColumn && isAllOverflow) {
sYHeight = afterFullData.length * defaultRowHeight;
if (sYHeight > maxYHeight) {
isScrollYBig = true;
}
ySpaceTop = Math.max(0, startIndex * defaultRowHeight);
}
else {
const firstRow = afterFullData[startIndex];
if (firstRow) {
let rowid = getRowid($xeTable, firstRow);
let rowRest = fullAllDataRowIdData[rowid] || {};
ySpaceTop = (rowRest.oTop || 0);
const lastRow = afterFullData[afterFullData.length - 1];
rowid = getRowid($xeTable, lastRow);
rowRest = fullAllDataRowIdData[rowid] || {};
if (rowRest) {
const rHeight = getCellRestHeight(rowRest, cellOpts, rowOpts, defaultRowHeight);
// 如果为空时还没计算完数据,保持原高度不变
if (rHeight) {
sYHeight = (rowRest.oTop || 0) + rHeight;
// 是否展开行
if (expandColumn && rowExpandedMaps[rowid]) {
sYHeight += rowRest.expandHeight || expandOpts.height || 0;
}
}
}
if (sYHeight > maxYHeight) {
isScrollYBig = true;
}
}
else {
sYHeight = bodyTableElem ? bodyTableElem.clientHeight : 0;
}
}
}
else {
if (bodyTableElem) {
sYHeight = bodyTableElem.clientHeight;
}
}
let clientHeight = 0;
if (bodyScrollElem) {
clientHeight = bodyScrollElem.clientHeight;
}
// 虚拟渲染
let ySpaceHeight = sYHeight;
let scrollYTop = ySpaceTop;
if (isScrollYBig) {
// 触底
if (bodyScrollElem && bodyTableElem && bodyScrollElem.scrollTop + clientHeight >= maxYHeight) {
scrollYTop = maxYHeight - bodyTableElem.clientHeight;
}
else {
scrollYTop = (maxYHeight - clientHeight) * (ySpaceTop / (scrollYHeight - clientHeight));
}
ySpaceHeight = maxYHeight;
}
if (!(scrollYLoad && overflowY)) {
scrollYTop = 0;
}
if (getConfig().scrollMarginStyle) {
if (leftBodyTableElem) {
leftBodyTableElem.style.marginTop = `${scrollYTop}px`;
}
if (bodyTableElem) {
bodyTableElem.style.marginTop = `${scrollYTop}px`;
}
if (rightbodyTableElem) {
rightbodyTableElem.style.marginTop = `${scrollYTop}px`;
}
}
else {
if (leftBodyTableElem) {
leftBodyTableElem.style.transform = `translate(0px, ${scrollYTop}px)`;
}
if (bodyTableElem) {
bodyTableElem.style.transform = `translate(${reactData.scrollXLeft || 0}px, ${scrollYTop}px)`;
}
if (rightbodyTableElem) {
rightbodyTableElem.style.transform = `translate(0px, ${scrollYTop}px)`;
}
}
containerList.forEach(name => {
const layoutList = ['header', 'body', 'footer'];
layoutList.forEach(layout => {
const ySpaceElem = getRefElem(elemStore[`${name}-${layout}-ySpace`]);
if (ySpaceElem) {
ySpaceElem.style.height = ySpaceHeight ? `${ySpaceHeight}px` : '';
}
});
});
const scrollYSpaceEl = refScrollYSpaceElem.value;
if (scrollYSpaceEl) {
scrollYSpaceEl.style.height = ySpaceHeight ? `${ySpaceHeight}px` : '';
}
const rowExpandYSpaceEl = refRowExpandYSpaceElem.value;
if (rowExpandYSpaceEl) {
rowExpandYSpaceEl.style.height = ySpaceHeight ? `${ySpaceHeight}px` : '';
}
reactData.scrollYTop = scrollYTop;
reactData.scrollYHeight = isScrollYBig ? sYHeight : ySpaceHeight;
reactData.isScrollYBig = isScrollYBig;
calcScrollbar();
if (isScrollYBig && mouseOpts.area) {
errLog('vxe.error.notProp', ['mouse-config.area']);
}
if ($xeGanttView && $xeGanttView.handleUpdateSYSpace) {
$xeGanttView.handleUpdateSYSpace();
}
return nextTick().then(() => {
return updateStyle();
});
},
updateScrollXData() {
const { isAllOverflow } = reactData;
handleTableColumn();
$xeTable.updateScrollXSpace();
return nextTick().then(() => {
handleTableColumn();
$xeTable.updateScrollXSpace();
if (!isAllOverflow) {
$xeTable.updateScrollYSpace();
}
});
},
updateScrollYData() {
$xeTable.handleTableData();
$xeTable.updateScrollYSpace();
return nextTick().then(() => {
$xeTable.handleTableData();
$xeTable.updateScrollYSpace();
});
},
/**
* 处理固定列的显示状态
*/
checkScrolling() {
const { elemStore } = internalData;
const bodyScrollElem = getRefElem(elemStore['main-body-scroll']);
const leftContainerElem = refLeftContainer.value;
const rightContainerElem = refRightContainer.value;
const xHandleEl = refScrollXHandleElem.value;
const bodtTargetEl = xHandleEl || bodyScrollElem;
if (bodtTargetEl) {
if (leftContainerElem) {
if (bodtTargetEl.scrollLeft > 0) {
addClass(leftContainerElem, 'scrolling--middle');
}
else {
removeClass(leftContainerElem, 'scrolling--middle');
}
}
if (rightContainerElem) {
if (bodtTargetEl.clientWidth < bodtTargetEl.scrollWidth - Math.ceil(bodtTargetEl.scrollLeft)) {
addClass(rightContainerElem, 'scrolling--middle');
}
else {
removeClass(rightContainerElem, 'scrolling--middle');
}
}
}
},
handleUpdateAggData() {
return loadTableData(internalData.tableSynchData, false, true);
},
handlePushStack() {
const keyboardOpts = computeKeyboardOpts.value;
if (!keyboardOpts.isUndoRedo) {
return;
}
const { stackHistoryStore } = internalData;
const stackObj = getSnapshotStackData();
stackHistoryStore.undoStacks.push(stackObj);
stackHistoryStore.redoStacks = [];
truncateStackHistory();
},
handleUndoStackEvent(evnt) {
const { stackHistoryStore } = internalData;
const { undoStacks, redoStacks } = stackHistoryStore;
if (undoStacks.length) {
const stackObj = getSnapshotStackData();
redoStacks.push(stackObj);
handleUpdateSnapshotStackData(undoStacks.pop());
if (evnt) {
dispatchEvent('undo', {}, evnt);
}
return nextTick(() => {
return { status: true };
});
}
return Promise.resolve({ status: false });
},
handleRedoStackEvent(evnt) {
const { stackHistoryStore } = internalData;
const { undoStacks, redoStacks } = stackHistoryStore;
if (redoStacks.length) {
const stackObj = getSnapshotStackData();
undoStacks.push(stackObj);
handleUpdateSnapshotStackData(redoStacks.pop());
if (evnt) {
dispatchEvent('redo', {}, evnt);
}
return nextTick(() => {
return { status: true };
});
}
return Promise.resolve({ status: false });
},
handleClearStack() {
const { stackHistoryStore } = internalData;
stackHistoryStore.undoStacks = [];
stackHistoryStore.redoStacks = [];
return nextTick();
},
updateZindex() {
if (props.zIndex) {
internalData.tZindex = props.zIndex;
}
else if (internalData.tZindex < getLastZIndex()) {
internalData.tZindex = nextZIndex();
}
},
handleCheckedCheckboxRow,
/**
* 行 hover 事件
*/
triggerHoverEvent(evnt, { row }) {
$xeTable.setHoverRow(row);
},
setHoverRow(row) {
const $xeGanttView = internalData.xeGanttView;
const rowid = getRowid($xeTable, row);
const el = refElem.value;
$xeTable.clearHoverRow();
if (el) {
XEUtils.arrayEach(el.querySelectorAll(`.vxe-body--row[rowid="${rowid}"]`), elem => addClass(elem, 'row--hover'));
}
internalData.hoverRow = row;
if ($xeGanttView && $xeGanttView.handleUpdateHoverRow) {
$xeGanttView.handleUpdateHoverRow(row);
}
},
clearHoverRow() {
const $xeGanttView = internalData.xeGanttView;
const el = refElem.value;
if (el) {
XEUtils.arrayEach(el.querySelectorAll('.vxe-body--row.row--hover'), elem => removeClass(elem, 'row--hover'));
}
internalData.hoverRow = null;
if ($xeGanttView && $xeGanttView.handleUpdateHoverRow) {
$xeGanttView.handleUpdateHoverRow();
}
},
/**
* 已废弃,被 getCellElement 替换
* @deprecated
*/
getCell(row, column) {
return $xeTable.getCellElement(row, column);
},
findRowIndexOf(list, row) {
return row ? XEUtils.findIndexOf(list, item => $xeTable.eqRow(item, row)) : -1;
},
eqRow(row1, row2) {
if (row1 && row2) {
if (row1 === row2) {
return true;
}
return getRowid($xeTable, row1) === getRowid($xeTable, row2);
}
return false;
},
handleConnectGanttView($ganttView) {
if ($ganttView && $ganttView.connectUpdate) {
$ganttView.connectUpdate({ $table: $xeTable });
internalData.xeGanttView = $ganttView;
}
return nextTick();
}
};
// 检测对应模块是否安装
// 'openExport,openPrint,exportData,openImport,importData,saveFile,readFile,importByFile,print'.split(',').forEach(name => {
// ($xeTable as any)[name] = function () {
// errLog('vxe.error.reqModule', ['Export'])
// }
// })
// 'clearValidate,fullValidate,validate'.split(',').forEach(name => {
// ($xeTable as any)[name] = function () {
// errLog('vxe.error.reqModule', ['Validator'])
// }
// })
Object.assign($xeTable, tableMethods, tablePrivateMethods);
/**
* 渲染浮固定列
* 分别渲染左边固定列和右边固定列
* 如果宽度足够情况下,则不需要渲染固定列
* @param {String} fixedType 固定列类型
*/
const renderViewFixed = (fixedType) => {
const { showHeader, showFooter } = props;
const { tableData, tableColumn, tableGroupColumn, columnStore, footerTableData } = reactData;
const scrollbarOpts = computeScrollbarOpts.value;
const scrollbarXOpts = computeScrollbarXOpts.value;
const scrollbarYOpts = computeScrollbarYOpts.value;
const { overscrollBehavior: overscrollXBehavior } = scrollbarXOpts;
const { overscrollBehavior: overscrollYBehavior } = scrollbarYOpts;
const isFixedLeft = fixedType === 'left';
const fixedColumn = isFixedLeft ? columnStore.leftList : columnStore.rightList;
const osXBehavior = XEUtils.eqNull(overscrollXBehavior) ? scrollbarOpts.overscrollBehavior : overscrollXBehavior;
const osYBehavior = XEUtils.eqNull(overscrollYBehavior) ? scrollbarOpts.overscrollBehavior : overscrollYBehavior;
return h('div', {
ref: isFixedLeft ? refLeftContainer : refRightContainer,
class: [`vxe-table--fixed-${fixedType}-wrapper`, `sx--${scrollbarXOpts.visible}`, `sy--${scrollbarYOpts.visible}`, {
[`x-ob--${osXBehavior}`]: osXBehavior,
[`y-ob--${osYBehavior}`]: osYBehavior
}]
}, [
showHeader
? h(TableHeaderComponent, {
ref: isFixedLeft ? refTableLeftHeader : refTableRightHeader,
fixedType,
tableData,
tableColumn,
tableGroupColumn,
fixedColumn
})
: renderEmptyElement($xeTable),
h(TableBodyComponent, {
ref: isFixedLeft ? refTableLeftBody : refTableRightBody,
fixedType,
tableData,
tableColumn,
fixedColumn
}),
showFooter
? h(TableFooterComponent, {
ref: isFixedLeft ? refTableLeftFooter : refTableRightFooter,
footerTableData,
tableColumn,
fixedColumn,
fixedType
})
: renderEmptyElement($xeTable)
]);
};
const renderEmptyBody = () => {
const emptyOpts = computeEmptyOpts.value;
const emptySlot = slots.empty;
const emptyParams = { $table: $xeTable, $grid: $xeGrid, gantt: $xeGantt };
if (emptySlot) {
return emptySlot(emptyParams);
}
else {
const compConf = emptyOpts.name ? renderer.get(emptyOpts.name) : null;
const rtEmptyView = compConf ? (compConf.renderTableEmpty || compConf.renderTableEmptyView || compConf.renderEmpty) : null;
if (rtEmptyView) {
return getSlotVNs(rtEmptyView(emptyOpts, emptyParams));
}
}
return getFuncText(props.emptyText) || getI18n('vxe.table.emptyText');
};
const renderDragTipContents = () => {
const { dragConfig } = props;
const { dragRow, dragCol, dragTipText } = reactData;
const columnDragOpts = computeColumnDragOpts.value;
const rowDragOpts = computeRowDragOpts.value;
const rowDragSlots = rowDragOpts.slots || {};
const rTipSlot = rowDragSlots.tip || (dragConfig && dragConfig.slots ? dragConfig.slots.rowTip : null);
const columnDragSlots = columnDragOpts.slots || {};
const cTipSlot = columnDragSlots.tip;
const dRow = dragRow || (rowDragOpts.isCrossTableDrag ? crossTableDragRowInfo.row : null);
if (dRow && rTipSlot) {
return callSlot(rTipSlot, { row: dRow });
}
if (dragCol && cTipSlot) {
return callSlot(cTipSlot, { column: dragCol });
}
return [h('span', dragTipText)];
};
const renderDragTip = () => {
const { dragRow, dragCol } = reactData;
const rowOpts = computeRowOpts.value;
const columnOpts = computeColumnOpts.value;
const rowDragOpts = computeRowDragOpts.value;
const columnDragOpts = computeColumnDragOpts.value;
const dRow = dragRow || (rowDragOpts.isCrossTableDrag ? crossTableDragRowInfo.row : null);
if (rowOpts.drag || columnOpts.drag) {
return h('div', {
class: 'vxe-table--drag-wrapper'
}, [
h('div', {
ref: refDragRowLineElem,
class: ['vxe-table--drag-row-line', {
'is--guides': rowDragOpts.showGuidesStatus
}]
}),
h('div', {
ref: refDragColLineElem,
class: ['vxe-table--drag-col-line', {
'is--guides': columnDragOpts.showGuidesStatus
}]
}),
(dRow && rowDragOpts.showDragTip) || (dragCol && columnDragOpts.showDragTip)
? h('div', {
ref: refDragTipElem,
class: 'vxe-table--drag-sort-tip'
}, [
h('div', {
class: 'vxe-table--drag-sort-tip-wrapper'
}, [
h('div', {
class: 'vxe-table--drag-sort-tip-status'
}, [
h('span', {
class: ['vxe-table--drag-sort-tip-normal-status', dRow ? getIcon().TABLE_DRAG_STATUS_ROW : getIcon().TABLE_DRAG_STATUS_COLUMN]
}),
h('span', {
class: ['vxe-table--drag-sort-tip-sub-status', getIcon().TABLE_DRAG_STATUS_SUB_ROW]
}),
h('span', {
class: ['vxe-table--drag-sort-tip-disabled-status', getIcon().TABLE_DRAG_DISABLED]
})
]),
h('div', {
class: 'vxe-table--drag-sort-tip-content'
}, renderDragTipContents())
])
])
: renderEmptyElement($xeTable)
]);
}
return renderEmptyElement($xeTable);
};
const renderRowExpandedVNs = () => {
const { treeConfig } = props;
const { expandColumn, isRowGroupStatus } = reactData;
const tableRowExpandedList = computeTableRowExpandedList.value;
const expandOpts = computeExpandOpts.value;
const { mode } = expandOpts;
if (mode !== 'fixed') {
return renderEmptyElement($xeTable);
}
const expandVNs = [
h('div', {
key: 'repY',
ref: refRowExpandYSpaceElem
})
];
if (expandColumn) {
const { handleGetRowId } = createHandleGetRowId($xeTable);
tableRowExpandedList.forEach((row) => {
const expandOpts = computeExpandOpts.value;
const { height: expandHeight, padding, indent } = expandOpts;
const { fullAllDataRowIdData, fullColumnIdData } = internalData;
const treeOpts = computeTreeOpts.value;
const { transform, seqMode } = treeOpts;
const cellStyle = {};
const rowid = handleGetRowId(row);
const rowRest = fullAllDataRowIdData[rowid];
const colid = expandColumn.id;
const colRest = fullColumnIdData[colid] || {};
let rowLevel = 0;
let seq = -1;
let _rowIndex = -1;
let rowIndex = -1;
let $rowIndex = -1;
if (rowRest) {
rowIndex = rowRest.index;
$rowIndex = rowRest.$index;
_rowIndex = rowRest._index;
rowLevel = rowRest.level;
seq = rowRest.seq;
if (isRowGroupStatus || (treeConfig && transform && seqMode === 'increasing')) {
seq = rowRest._index + 1;
}
else if ((treeConfig && seqMode === 'fixed')) {
seq = rowRest._tIndex + 1;
}
}
if (expandHeight) {
cellStyle.height = `${expandHeight}px`;
}
if (isRowGroupStatus || treeConfig) {
cellStyle.paddingLeft = `${(rowLevel * (XEUtils.isNumber(indent) ? indent : treeOpts.indent)) + 30}px`;
}
let columnIndex = -1;
let $columnIndex = -1;
let _columnIndex = -1;
if (colRest) {
columnIndex = colRest.index;
$columnIndex = colRest.$index;
_columnIndex = colRest._index;
}
const expandParams = {
$table: $xeTable,
$grid: $xeGrid,
$gantt: $xeGantt,
seq,
column: expandColumn,
columnIndex,
$columnIndex,
_columnIndex,
fixed: '',
source: 'table',
type: 'body',
level: rowLevel,
rowid,
row,
rowIndex,
$rowIndex,
_rowIndex,
isHidden: false,
isEdit: false,
visibleData: [],
data: [],
items: []
};
expandVNs.push(h('div', {
key: rowid,
class: ['vxe-body--row-expanded-cell', {
'is--padding': padding,
'is--ellipsis': expandHeight
}],
rowid,
style: cellStyle
}, [
h('div', {
class: 'vxe-body--row-expanded-content'
}, expandColumn.renderData(expandParams))
]));
});
}
return h('div', {
ref: refRowExpandElem,
class: 'vxe-table--row-expanded-wrapper'
}, expandVNs);
};
const renderScrollX = () => {
return h('div', {
key: 'vsx',
ref: refScrollXVirtualElem,
class: 'vxe-table--scroll-x-virtual'
}, [
h('div', {
ref: refScrollXLeftCornerElem,
class: 'vxe-table--scroll-x-left-corner'
}),
h('div', {
ref: refScrollXWrapperElem,
class: 'vxe-table--scroll-x-wrapper'
}, [
h('div', {
ref: refScrollXHandleElem,
class: 'vxe-table--scroll-x-handle',
onScroll: $xeTable.triggerVirtualScrollXEvent
}, [
h('div', {
ref: refScrollXSpaceElem,
class: 'vxe-table--scroll-x-space'
})
]),
h('div', {
class: 'vxe-table--scroll-x-handle-appearance'
})
]),
h('div', {
ref: refScrollXRightCornerElem,
class: 'vxe-table--scroll-x-right-corner'
})
]);
};
const renderScrollY = () => {
return h('div', {
ref: refScrollYVirtualElem,
class: 'vxe-table--scroll-y-virtual'
}, [
h('div', {
ref: refScrollYTopCornerElem,
class: 'vxe-table--scroll-y-top-corner'
}),
h('div', {
ref: refScrollYWrapperElem,
class: 'vxe-table--scroll-y-wrapper'
}, [
h('div', {
ref: refScrollYHandleElem,
class: 'vxe-table--scroll-y-handle',
onScroll: $xeTable.triggerVirtualScrollYEvent
}, [
h('div', {
ref: refScrollYSpaceElem,
class: 'vxe-table--scroll-y-space'
})
]),
h('div', {
class: 'vxe-table--scroll-y-handle-appearance'
})
]),
h('div', {
ref: refScrollYBottomCornerElem,
class: 'vxe-table--scroll-y-bottom-corner'
})
]);
};
const renderViewport = () => {
const { showHeader, showFooter } = props;
const { overflowX, tableData, tableColumn, tableGroupColumn, footerTableData, columnStore } = reactData;
const scrollbarOpts = computeScrollbarOpts.value;
const scrollbarXOpts = computeScrollbarXOpts.value;
const scrollbarYOpts = computeScrollbarYOpts.value;
const { overscrollBehavior: overscrollXBehavior } = scrollbarXOpts;
const { overscrollBehavior: overscrollYBehavior } = scrollbarYOpts;
const { leftList, rightList } = columnStore;
const osXBehavior = XEUtils.eqNull(overscrollXBehavior) ? scrollbarOpts.overscrollBehavior : overscrollXBehavior;
const osYBehavior = XEUtils.eqNull(overscrollYBehavior) ? scrollbarOpts.overscrollBehavior : overscrollYBehavior;
return h('div', {
ref: refTableViewportElem,
class: ['vxe-table--viewport-wrapper', {
[`x-ob--${osXBehavior}`]: osXBehavior,
[`y-ob--${osYBehavior}`]: osYBehavior
}]
}, [
h('div', {
class: ['vxe-table--main-wrapper', `sx--${scrollbarXOpts.visible}`, `sy--${scrollbarYOpts.visible}`]
}, [
/**
* 表头
*/
showHeader
? h(TableHeaderComponent, {
ref: refTableHeader,
tableData,
tableColumn,
tableGroupColumn
})
: renderEmptyElement($xeTable),
/**
* 表体
*/
h(TableBodyComponent, {
ref: refTableBody,
tableData,
tableColumn
}),
/**
* 表尾
*/
showFooter
? h(TableFooterComponent, {
ref: refTableFooter,
footerTableData,
tableColumn
})
: renderEmptyElement($xeTable)
]),
h('div', {
class: 'vxe-table--fixed-wrapper'
}, [
leftList && leftList.length && overflowX ? renderViewFixed('left') : renderEmptyElement($xeTable),
rightList && rightList.length && overflowX ? renderViewFixed('right') : renderEmptyElement($xeTable)
]),
renderRowExpandedVNs()
]);
};
const renderBody = () => {
const scrollbarYToLeft = computeScrollbarYToLeft.value;
return h('div', {
class: 'vxe-table--layout-wrapper'
}, scrollbarYToLeft
? [
renderScrollY(),
renderViewport()
]
: [
renderViewport(),
renderScrollY()
]);
};
const renderVN = () => {
const { loading, stripe, showHeader, height, treeConfig, mouseConfig, showFooter, highlightCell, highlightHoverRow, highlightHoverColumn, editConfig, editRules } = props;
const { isGroup, overflowX, overflowY, scrollXLoad, scrollYLoad, tableData, initStore, isRowGroupStatus, columnStore, filterStore, customStore, tooltipStore } = reactData;
const { teleportToWrapperElem, popupToWrapperElem, customPopupToElem } = internalData;
const { leftList, rightList } = columnStore;
const loadingSlot = slots.loading;
const tipSlots = {
header: slots.headerTooltip || slots['header-tooltip'],
body: slots.tooltip,
footer: slots.footerTooltip || slots['footer-tooltip']
};
const currTooltipSlot = tooltipStore.visible && tooltipStore.type ? tipSlots[tooltipStore.type] : null;
const tableStyle = computeTableStyle.value;
const rowDragOpts = computeRowDragOpts.value;
const tableTipConfig = computeTableTipConfig.value;
const validTipConfig = computeValidTipConfig.value;
const validOpts = computeValidOpts.value;
const checkboxOpts = computeCheckboxOpts.value;
const treeOpts = computeTreeOpts.value;
const rowOpts = computeRowOpts.value;
const columnOpts = computeColumnOpts.value;
const vSize = computeSize.value;
const tableBorder = computeTableBorder.value;
const mouseOpts = computeMouseOpts.value;
const areaOpts = computeAreaOpts.value;
const loadingOpts = computeLoadingOpts.value;
const isContentMenu = computeIsContentMenu.value;
const currLoading = reactData.isColLoading || reactData.isRowLoading || loading;
const resizableOpts = computeResizableOpts.value;
const isArea = mouseConfig && mouseOpts.area;
const columnDragOpts = computeColumnDragOpts.value;
const scrollbarXToTop = computeScrollbarXToTop.value;
const scrollbarYToLeft = computeScrollbarYToLeft.value;
const { isCrossTableDrag } = rowDragOpts;
const tbOns = {
onKeydown: keydownEvent,
onContextmenu: contextMenuEvent
};
if (isCrossTableDrag && !tableData.length) {
tbOns.onDragover = $xeTable.handleCrossTableRowDragoverEmptyEvent;
}
return h('div', Object.assign({ ref: refElem, class: ['vxe-table', 'vxe-table--render-default', `tid_${xID}`, `border--${tableBorder}`, `sx-pos--${scrollbarXToTop ? 'top' : 'bottom'}`, `sy-pos--${scrollbarYToLeft ? 'left' : 'right'}`, {
[`size--${vSize}`]: vSize,
[`valid-msg--${validOpts.msgMode}`]: !!editRules,
'vxe-editable': !!editConfig,
'old-cell-valid': editRules && getConfig().cellVaildMode === 'obsolete',
'cell--highlight': highlightCell,
'cell--selected': mouseConfig && mouseOpts.selected,
'cell--area': isArea,
'header-cell--area': isArea && areaOpts.selectCellByHeader,
'body-cell--area': isArea && areaOpts.selectCellByBody,
'row--highlight': rowOpts.isHover || highlightHoverRow,
'column--highlight': columnOpts.isHover || highlightHoverColumn,
'checkbox--range': checkboxOpts.range,
'col--drag-cell': columnOpts.drag && columnDragOpts.trigger === 'cell',
'is--header': showHeader,
'not--header': !showHeader,
'is--footer': showFooter,
'not--footer': !showFooter,
'is--group': isGroup,
'is-row-group': isRowGroupStatus,
'is--tree-line': treeConfig && (treeOpts.showLine || treeOpts.line),
'is--fixed-left': leftList.length,
'is--fixed-right': rightList.length,
'is--animat': !!props.animat,
'is--round': props.round,
'is--stripe': !treeConfig && stripe,
'is--loading': currLoading,
'is--empty': !currLoading && !tableData.length,
'is--scroll-y': overflowY,
'not--scroll-y': !overflowY,
'is--scroll-x': overflowX,
'not--scroll-x': !overflowX,
'is--virtual-x': scrollXLoad,
'is--virtual-y': scrollYLoad
}], style: tableStyle, spellcheck: false }, tbOns), [
/**
* 隐藏列
*/
h('div', {
class: 'vxe-table-slots'
}, slots.default ? slots.default({}) : []),
h('div', {
ref: refVarElem,
class: 'vxe-table-vars'
}, [
h('div', {
class: 'vxe-table-var-default'
}),
h('div', {
class: 'vxe-table-var-medium'
}),
h('div', {
class: 'vxe-table-var-small'
}),
h('div', {
class: 'vxe-table-var-mini'
})
]),
h('div', {
key: 'tw',
class: 'vxe-table--render-wrapper'
}, scrollbarXToTop
? [
renderScrollX(),
renderBody()
]
: [
renderBody(),
renderScrollX()
]),
/**
* 空数据
*/
h('div', {
key: 'tn',
ref: refEmptyPlaceholder,
class: 'vxe-table--empty-place-wrapper',
xid: xID
}, [
h('div', {
class: 'vxe-table--empty-placeholder'
}, [
h('div', {
class: 'vxe-table--empty-content'
}, renderEmptyBody())
])
]),
/**
* 边框线
*/
h('div', {
key: 'tl',
class: 'vxe-table--border-line'
}),
/**
* 列宽线
*/
h('div', {
key: 'tcl',
ref: refColResizeBar,
class: 'vxe-table--resizable-col-bar'
}, resizableOpts.showDragTip
? [
h('div', {
class: 'vxe-table--resizable-number-tip'
})
]
: []),
h('div', {
key: 'ttw'
}, [
h(Teleport, {
to: teleportToWrapperElem,
disabled: !($xeGantt && teleportToWrapperElem)
}, [
h('div', {
ref: refTeleportWrapper
}, [
/**
* 行高线
*/
h('div', {
key: 'trl',
ref: refRowResizeBar,
class: 'vxe-table--resizable-row-bar'
}, resizableOpts.showDragTip
? [
h('div', {
class: 'vxe-table--resizable-number-tip'
})
]
: []),
/**
* 加载中
*/
VxeUILoadingComponent
? h(VxeUILoadingComponent, {
key: 'lg',
class: 'vxe-table--loading',
modelValue: currLoading,
icon: loadingOpts.icon,
text: loadingOpts.text
}, loadingSlot
? {
default: () => callSlot(loadingSlot, { $table: $xeTable, $grid: $xeGrid, $gantt: $xeGantt, loading: currLoading })
}
: {})
: loadingSlot
? h('div', {
class: ['vxe-loading--custom-wrapper', {
'is--visible': currLoading
}]
}, callSlot(loadingSlot, { $table: $xeTable, $grid: $xeGrid, $gantt: $xeGantt, loading: currLoading }))
: renderEmptyElement($xeTable),
/**
* 拖拽排序提示
*/
renderDragTip()
])
])
]),
h('div', {
key: 'fpw',
ref: refCustomContainerElem
}, [
h(Teleport, {
to: customPopupToElem,
disabled: !!reactData.ctPopupFlag && !customPopupToElem
}, [
/**
* 自定义列
*/
initStore.custom
? h(TableCustomPanelComponent, {
key: 'cs',
ref: refTableCustom,
customStore
})
: renderEmptyElement($xeTable)
])
]),
h('div', {
key: 'tpw'
}, [
h(Teleport, {
to: popupToWrapperElem,
disabled: !($xeGGWrapper && popupToWrapperElem)
}, [
h('div', {
ref: refPopupWrapperElem
}, [
/**
* 筛选
*/
initStore.filter
? h(TableFilterPanelComponent, {
key: 'tf',
ref: refTableFilter,
filterStore
})
: renderEmptyElement($xeTable),
/**
* 快捷菜单
*/
isContentMenu
? h(TableMenuPanelComponent, {
key: 'tm',
ref: refTableMenu
})
: renderEmptyElement($xeTable)
])
])
]),
/**
* 导入
*/
initStore.import && props.importConfig
? h(TableImportPanelComponent, {
key: 'it',
defaultOptions: reactData.importParams,
storeData: reactData.importStore
})
: renderEmptyElement($xeTable),
/**
* 导出
*/
initStore.export && (props.exportConfig || props.printConfig)
? h(TableExportPanelComponent, {
key: 'et',
defaultOptions: reactData.exportParams,
storeData: reactData.exportStore
})
: renderEmptyElement($xeTable),
/**
* 提示相关
*/
VxeUITooltipComponent
? h('div', {}, [
/**
* 通用提示
*/
h(VxeUITooltipComponent, {
key: 'ctp',
ref: refCommTooltip,
isArrow: false,
enterable: false
}),
/**
* 工具提示
*/
h(VxeUITooltipComponent, {
key: 'btp',
ref: refTooltip,
theme: tableTipConfig.theme,
enterable: tableTipConfig.enterable,
enterDelay: tableTipConfig.enterDelay,
leaveDelay: tableTipConfig.leaveDelay,
useHtml: XEUtils.isBoolean(tableTipConfig.useHtml) ? tableTipConfig.useHtml : undefined,
// 已废弃
useHTML: XEUtils.isBoolean(tableTipConfig.useHTML) ? tableTipConfig.useHTML : undefined,
width: tableTipConfig.width,
height: tableTipConfig.height,
minWidth: tableTipConfig.minWidth,
minHeight: tableTipConfig.minHeight,
maxWidth: tableTipConfig.maxWidth,
maxHeight: tableTipConfig.maxHeight,
placement: tableTipConfig.placement,
defaultPlacement: tableTipConfig.defaultPlacement,
popupClassName: tableTipConfig.popupClassName
}, currTooltipSlot
? {
content: () => {
const { type, row, column, content: tooltipContent } = tooltipStore;
if (currTooltipSlot) {
if (column && type === 'header') {
return h('div', {
key: type
}, currTooltipSlot({ column, tooltipContent, $table: $xeTable, $grid: $xeGrid, $gantt: $xeGantt }));
}
if (row && column && type === 'body') {
return h('div', {
key: type
}, currTooltipSlot({ row, column, tooltipContent, $table: $xeTable, $grid: $xeGrid, $gantt: $xeGantt }));
}
if (row && column && type === 'footer') {
return h('div', {
key: type
}, currTooltipSlot({ row, column, tooltipContent, $table: $xeTable, $grid: $xeGrid, $gantt: $xeGantt }));
}
}
return renderEmptyElement($xeTable);
}
}
: {}),
/**
* 校验提示
*/
props.editRules && validOpts.showErrorMessage && (validOpts.message === 'default' ? !height : validOpts.message === 'tooltip')
? h(VxeUITooltipComponent, {
key: 'vtp',
ref: refValidTooltip,
class: [{
'old-cell-valid': editRules && getConfig().cellVaildMode === 'obsolete'
}, 'vxe-table--valid-error'],
theme: validTipConfig.theme,
enterable: validTipConfig.enterable,
enterDelay: validTipConfig.enterDelay,
leaveDelay: validTipConfig.leaveDelay
})
: renderEmptyElement($xeTable)
])
: renderEmptyElement($xeTable)
]);
};
const dataFlag = ref(0);
watch(() => props.data ? props.data.length : -1, () => {
dataFlag.value++;
});
watch(() => props.data, () => {
dataFlag.value++;
});
watch(dataFlag, () => {
const { initStatus } = internalData;
const value = props.data || [];
if (value && value.length >= 20000) {
warnLog('vxe.error.errLargeData', ['loadData(data), reloadData(data)']);
}
loadTableData(value, false, true).then(() => {
const { scrollXLoad, scrollYLoad, expandColumn } = reactData;
const expandOpts = computeExpandOpts.value;
internalData.inited = true;
internalData.initStatus = true;
if (!initStatus) {
handleLoadDefaults();
}
// const checkboxOpts = computeCheckboxOpts.value
// const checkboxColumn = internalData.tableFullColumn.find(column => column.type === 'checkbox')
// if (checkboxColumn && internalData.tableFullData.length > 300 && !checkboxOpts.checkField) {
// warnLog('vxe.error.checkProp', ['checkbox-config.checkField'])
// }
if ((scrollXLoad || scrollYLoad) && (expandColumn && expandOpts.mode !== 'fixed')) {
warnLog('vxe.error.scrollErrProp', ['column.type=expand']);
}
return $xeTable.recalculate();
});
});
const staticColumnFlag = ref(0);
watch(() => reactData.staticColumns.length, () => {
staticColumnFlag.value++;
});
watch(() => reactData.staticColumns, () => {
staticColumnFlag.value++;
});
watch(staticColumnFlag, () => {
nextTick(() => handleInitColumn(XEUtils.clone(reactData.staticColumns)));
});
const tableColumnFlag = ref(0);
watch(() => reactData.tableColumn.length, () => {
tableColumnFlag.value++;
});
watch(() => reactData.tableColumn, () => {
tableColumnFlag.value++;
});
watch(tableColumnFlag, () => {
$xeTable.analyColumnWidth();
});
watch(() => reactData.upDataFlag, () => {
nextTick(() => {
$xeTable.updateData();
});
});
watch(() => reactData.reColumnFlag, () => {
nextTick(() => {
$xeTable.refreshColumn();
});
});
const reLayoutFlag = ref(0);
watch(computeSize, () => {
reLayoutFlag.value++;
});
watch(() => props.showHeader, () => {
reLayoutFlag.value++;
});
watch(() => props.showFooter, () => {
reLayoutFlag.value++;
});
watch(() => props.showHeaderOverflow, () => {
reLayoutFlag.value++;
});
watch(() => props.showOverflow, () => {
updateColumnAllOverflow();
reLayoutFlag.value++;
});
watch(() => props.showFooterOverflow, () => {
reLayoutFlag.value++;
});
watch(() => reactData.overflowX, () => {
reLayoutFlag.value++;
});
watch(() => reactData.overflowY, () => {
reLayoutFlag.value++;
});
watch(() => props.height, () => {
reLayoutFlag.value++;
});
watch(() => props.maxHeight, () => {
reLayoutFlag.value++;
});
watch(computeScrollbarXToTop, () => {
reLayoutFlag.value++;
});
watch(computeScrollbarYToLeft, () => {
reLayoutFlag.value++;
});
watch(() => VxeUI.getLanguage(), () => {
reLayoutFlag.value++;
});
watch(() => {
const scrollbarXOpts = computeScrollbarXOpts.value;
return scrollbarXOpts.visible;
}, () => {
reLayoutFlag.value++;
});
watch(() => {
const scrollbarYOpts = computeScrollbarYOpts.value;
return scrollbarYOpts.visible;
}, () => {
reLayoutFlag.value++;
});
watch(() => {
const cellOpts = computeCellOpts.value;
return cellOpts.height;
}, () => {
reLayoutFlag.value++;
});
watch(reLayoutFlag, () => {
$xeTable.recalculate(true);
});
const footFlag = ref(0);
watch(() => props.footerData ? props.footerData.length : -1, () => {
footFlag.value++;
});
watch(() => props.footerData, () => {
footFlag.value++;
});
watch(footFlag, () => {
internalData.footerFullDataRowData = {};
$xeTable.updateFooter();
});
watch(() => props.syncResize, (value) => {
if (value) {
handleUpdateResize();
nextTick(() => {
handleUpdateResize();
setTimeout(() => handleUpdateResize());
});
}
});
const mergeCellFlag = ref(0);
watch(() => props.mergeCells ? props.mergeCells.length : -1, () => {
mergeCellFlag.value++;
});
watch(() => props.mergeCells, () => {
mergeCellFlag.value++;
});
watch(mergeCellFlag, () => {
handleUpdateMergeBodyCells(props.mergeCells || []);
});
const mergeHeaderItemFlag = ref(0);
watch(() => props.mergeHeaderCells ? props.mergeHeaderCells.length : -1, () => {
mergeHeaderItemFlag.value++;
});
watch(() => props.mergeHeaderCells, () => {
mergeHeaderItemFlag.value++;
});
watch(mergeHeaderItemFlag, () => {
handleUpdateMergeHeaderCells(props.mergeHeaderCells || []);
});
const mergeFooteCellFlag = ref(0);
watch(() => props.mergeFooterCells ? props.mergeFooterCells.length : -1, () => {
mergeFooteCellFlag.value++;
});
watch(() => props.mergeFooterCells, () => {
mergeFooteCellFlag.value++;
});
watch(() => props.mergeFooterItems ? props.mergeFooterItems.length : -1, () => {
mergeFooteCellFlag.value++;
});
watch(() => props.mergeFooterItems, () => {
mergeFooteCellFlag.value++;
});
watch(mergeFooteCellFlag, () => {
const mFooterCells = props.mergeFooterCells || props.mergeFooterItems;
handleUpdateMergeFooterCells(mFooterCells || []);
});
watch(computeRowGroupFields, (val) => {
handleUpdateRowGroup(val);
});
watch(computeRowField, () => {
const { inited, tableFullData } = internalData;
// 行主键被改变,重载表格
if (inited) {
handleKeyField();
reactData.tableData = [];
nextTick(() => {
$xeTable.reloadData(tableFullData);
});
}
});
const kfFlag = ref(0);
watch(() => reactData.updateColFlag, () => {
kfFlag.value++;
});
watch(computeKeepFields, () => {
kfFlag.value++;
});
watch(kfFlag, () => {
const keepFields = computeKeepFields.value;
const kpfMaps = {};
keepFields.forEach(field => {
kpfMaps[field] = 1;
});
internalData.keepUpdateFieldMaps = kpfMaps;
});
watch(computeAggregateMode, () => {
if (reactData.isRowGroupStatus) {
loadTableData(internalData.tableSynchData, false, true);
}
});
const layoutReFlag = ref(0);
watch(combineTabsResizeFlag, () => {
layoutReFlag.value++;
});
watch(combineModalResizeFlag, () => {
layoutReFlag.value++;
});
watch(combineSplitterResizeFlag, () => {
layoutReFlag.value++;
});
watch(layoutReFlag, () => {
handleGlobalResizeEvent();
});
handleKeyField();
hooks.forEach((options) => {
const { setupTable } = options;
if (setupTable) {
const hookRest = setupTable($xeTable);
if (hookRest && XEUtils.isObject(hookRest)) {
Object.assign($xeTable, hookRest);
}
}
});
$xeTable.preventEvent(null, 'created', { $table: $xeTable });
let resizeObserver;
onActivated(() => {
$xeTable.recalculate().then(() => $xeTable.refreshScroll());
$xeTable.preventEvent(null, 'activated', { $table: $xeTable });
});
onDeactivated(() => {
const { filterStore } = reactData;
if (filterStore.visible) {
$xeTable.clearFilter();
}
$xeTable.closeTooltip();
internalData.isActivated = false;
$xeTable.preventEvent(null, 'deactivated', { $table: $xeTable });
});
onMounted(() => {
const { editConfig, exportConfig, importConfig, treeConfig, minHeight, keepSource } = props;
const { scrollXStore, scrollYStore } = internalData;
const columnOpts = computeColumnOpts.value;
const columnDragOpts = computeColumnDragOpts.value;
const aggregateOpts = computeAggregateOpts.value;
const virtualYOpts = computeVirtualYOpts.value;
const editOpts = computeEditOpts.value;
const treeOpts = computeTreeOpts.value;
const radioOpts = computeRadioOpts.value;
const checkboxOpts = computeCheckboxOpts.value;
const expandOpts = computeExpandOpts.value;
const rowOpts = computeRowOpts.value;
const customOpts = computeCustomOpts.value;
const mouseOpts = computeMouseOpts.value;
const exportOpts = computeExportOpts.value;
const importOpts = computeImportOpts.value;
// const currentRowOpts = computeCurrentRowOpts.value
// const currentColumnOpts = computeCurrentColumnOpts.value
// const keyboardOpts = computeKeyboardOpts.value
const rowDragOpts = computeRowDragOpts.value;
const areaOpts = computeAreaOpts.value;
const sortOpts = computeSortOpts.value;
const filterOpts = computeFilterOpts.value;
const { groupFields } = aggregateOpts;
if ($xeGantt) {
const { refClassifyWrapperElem } = $xeGantt.getRefMaps();
const classifyWrapperEl = refClassifyWrapperElem.value;
if (classifyWrapperEl) {
internalData.teleportToWrapperElem = classifyWrapperEl;
}
}
if ($xeGGWrapper) {
const { refPopupContainerElem } = $xeGGWrapper.getRefMaps();
const popupContainerEl = refPopupContainerElem.value;
if (popupContainerEl) {
internalData.popupToWrapperElem = popupContainerEl;
}
}
if (columnOpts.drag || rowOpts.drag || customOpts.allowSort) {
initTpImg();
}
if (props.rowId) {
warnLog('vxe.error.delProp', ['row-id', 'row-config.keyField']);
}
if (props.rowKey) {
warnLog('vxe.error.delProp', ['row-key', 'row-config.useKey']);
}
if (props.columnKey) {
warnLog('vxe.error.delProp', ['column-id', 'column-config.useKey']);
}
if (!(props.rowId || rowOpts.keyField) && (checkboxOpts.reserve || checkboxOpts.checkRowKeys || radioOpts.reserve || radioOpts.checkRowKey || expandOpts.expandRowKeys || treeOpts.expandRowKeys)) {
warnLog('vxe.error.reqProp', ['row-config.keyField']);
}
if (editConfig) {
if (!keepSource) {
if (editOpts.showStatus || editOpts.showUpdateStatus || editOpts.showInsertStatus) {
warnLog('vxe.error.reqSupportProp', ['edit-config.showStatus | showUpdateStatus | showInsertStatus', 'keep-source']);
}
// if (keyboardOpts.isUndoRedo) {
// warnLog('vxe.error.reqSupportProp', ['keyboard-config.isUndoRedo', 'keep-source'])
// }
}
}
// if (treeConfig && (treeOpts.showLine || treeOpts.line) && !showOverflow) {
// warnLog('vxe.error.reqProp', ['show-overflow'])
// }
// if (treeConfig && !treeOpts.transform && props.stripe) {
// warnLog('vxe.error.noTree', ['stripe'])
// }
if (treeConfig && !treeOpts.transform) {
if (sortOpts.isDeep) {
warnLog('vxe.error.reqSupportProp', ['transform=false', 'sort-config.isDeep=false']);
}
if (filterOpts.isDeep) {
warnLog('vxe.error.reqSupportProp', ['transform=false', 'filter-config.isDeep=false']);
}
}
if (props.showFooter && !(props.footerMethod || props.footerData)) {
warnLog('vxe.error.reqProp', ['footer-data | footer-method']);
}
if (rowOpts.height) {
warnLog('vxe.error.delProp', ['row-config.height', 'cell-config.height']);
}
if (props.highlightCurrentRow) {
warnLog('vxe.error.delProp', ['highlight-current-row', 'row-config.isCurrent']);
}
if (props.highlightHoverRow) {
warnLog('vxe.error.delProp', ['highlight-hover-row', 'row-config.isHover']);
}
if (props.highlightCurrentColumn) {
warnLog('vxe.error.delProp', ['highlight-current-column', 'column-config.isCurrent']);
}
if (props.highlightHoverColumn) {
warnLog('vxe.error.delProp', ['highlight-hover-column', 'column-config.isHover']);
}
if (props.resizable) {
warnLog('vxe.error.delProp', ['resizable', 'column-config.resizable']);
}
// if (props.virtualXConfig && props.scrollX) {
// warnLog('vxe.error.notSupportProp', ['virtual-x-config', 'scroll-x', 'scroll-x=null'])
// }
// if (props.virtualYConfig && props.scrollY) {
// warnLog('vxe.error.notSupportProp', ['virtual-y-config', 'scroll-y', 'scroll-y=null'])
// }
if (props.aggregateConfig && props.rowGroupConfig) {
warnLog('vxe.error.notSupportProp', ['aggregate-config', 'row-group-config', 'row-group-config=null']);
}
// if (props.scrollY) {
// warnLog('vxe.error.delProp', ['scroll-y', 'virtual-y-config'])
// }
// if (props.scrollX) {
// warnLog('vxe.error.delProp', ['scroll-x', 'virtual-x-config'])
// }
// 检查导入导出类型,如果自定义导入导出方法,则不校验类型
if (importConfig && importOpts.types && !importOpts.importMethod && !XEUtils.includeArrays(XEUtils.keys(importOpts._typeMaps), importOpts.types)) {
warnLog('vxe.error.errProp', [`export-config.types=${importOpts.types.join(',')}`, importOpts.types.filter((type) => XEUtils.includes(XEUtils.keys(importOpts._typeMaps), type)).join(',') || XEUtils.keys(importOpts._typeMaps).join(',')]);
}
if (exportConfig && exportOpts.types && !exportOpts.exportMethod && !XEUtils.includeArrays(XEUtils.keys(exportOpts._typeMaps), exportOpts.types)) {
warnLog('vxe.error.errProp', [`export-config.types=${exportOpts.types.join(',')}`, exportOpts.types.filter((type) => XEUtils.includes(XEUtils.keys(exportOpts._typeMaps), type)).join(',') || XEUtils.keys(exportOpts._typeMaps).join(',')]);
}
if (exportConfig && XEUtils.isBoolean(exportOpts.isAllExpand)) {
warnLog('vxe.error.delProp', ['isAllExpand', 'isTreeAllExpanded']);
}
if (!props.id) {
if ((props.customConfig ? isEnableConf(customOpts) : customOpts.enabled) && customOpts.storage) {
errLog('vxe.error.reqProp', ['id']);
}
}
if (props.treeConfig && checkboxOpts.range) {
errLog('vxe.error.noTree', ['checkbox-config.range']);
}
if (rowOpts.height && !props.showOverflow) {
warnLog('vxe.error.notProp', ['table.show-overflow']);
}
if (!$xeTable.triggerClAreaMnEvent) {
if (props.areaConfig) {
warnLog('vxe.error.notProp', ['area-config']);
}
if (props.clipConfig) {
warnLog('vxe.error.notProp', ['clip-config']);
}
if (props.fnrConfig) {
warnLog('vxe.error.notProp', ['fnr-config']);
}
if (mouseOpts.area) {
errLog('vxe.error.notProp', ['mouse-config.area']);
return;
}
if (mouseOpts.area && areaOpts.selectCellByHeader && columnOpts.drag && columnDragOpts.trigger === 'cell') {
errLog('vxe.error.notSupportProp', ['area-config.selectCellByHeader & column-config.drag', 'column-drag-config.trigger=cell', 'column-drag-config.trigger=default | area-config.selectCellByHeader=false']);
}
}
if (!$xeTable.handlePivotTableAggData) {
if (customOpts.allowGroup) {
errLog('vxe.error.notProp', ['custom-config.allowGroup']);
return;
}
if (customOpts.allowValues) {
errLog('vxe.error.notProp', ['custom-config.allowValues']);
return;
}
}
if (treeConfig && rowOpts.drag && !treeOpts.transform) {
errLog('vxe.error.notSupportProp', ['row-config.drag', 'tree-config.transform=false', 'tree-config.transform=true']);
}
if (treeConfig && rowDragOpts.isCrossTableDrag && !rowDragOpts.isCrossDrag) {
errLog('vxe.error.reqSupportProp', ['tree-config & row-drag-config.isCrossTableDrag', 'row-drag-config.isCrossDrag']);
}
if (props.dragConfig) {
warnLog('vxe.error.delProp', ['drag-config', 'row-drag-config']);
}
if (props.rowGroupConfig) {
warnLog('vxe.error.delProp', ['row-group-config', 'aggregate-config']);
}
if (aggregateOpts.countFields) {
warnLog('vxe.error.delProp', ['row-group-config.countFields', 'column.agg-func']);
}
if (aggregateOpts.aggregateMethod) {
warnLog('vxe.error.delProp', ['row-group-config.aggregateMethod', 'aggregate-config.calcValuesMethod']);
}
if (aggregateOpts.countMethod) {
warnLog('vxe.error.delProp', ['aggregate-config.countMethod', 'aggregate-config.calcValuesMethod']);
}
if (props.treeConfig && treeOpts.children) {
warnLog('vxe.error.delProp', ['tree-config.children', 'tree-config.childrenField']);
}
if (props.treeConfig && treeOpts.line) {
warnLog('vxe.error.delProp', ['tree-config.line', 'tree-config.showLine']);
}
if (mouseOpts.area && mouseOpts.selected) {
warnLog('vxe.error.errConflicts', ['mouse-config.area', 'mouse-config.selected']);
}
if (mouseOpts.area && (props.treeConfig && !treeOpts.transform)) {
errLog('vxe.error.notSupportProp', ['mouse-config.area', 'tree-config.transform=false', 'tree-config.transform=true']);
}
if (props.editConfig && editOpts.activeMethod) {
warnLog('vxe.error.delProp', ['edit-config.activeMethod', 'edit-config.beforeEditMethod']);
}
if (checkboxOpts.halfField) {
warnLog('vxe.error.delProp', ['checkbox-config.halfField', 'checkbox-config.indeterminateField']);
}
if (props.editConfig && isEnableConf(editOpts) && props.editRules && (minHeight === 0 || minHeight === '0')) {
warnLog('vxe.error.reqSupportProp', ['edit-config & edit-rules', 'min-height']);
}
if (treeConfig) {
XEUtils.arrayEach(['rowField', 'parentField', 'childrenField', 'hasChildField', 'mapChildrenField'], key => {
const val = treeOpts[key];
if (val && val.indexOf('.') > -1) {
errLog('vxe.error.errProp', [`${key}=${val}`, `${key}=${val.split('.')[0]}`]);
}
});
}
if (rowOpts.currentMethod) {
warnLog('vxe.error.delProp', ['row-config.currentMethod', 'current-row-config.beforeSelectMethod']);
}
if (columnOpts.currentMethod) {
warnLog('vxe.error.delProp', ['row-config.currentMethod', 'current-column-config.beforeSelectMethod']);
}
// if ((rowOpts.isCurrent || highlightCurrentRow) && props.keyboardConfig && keyboardOpts.isArrow && !XEUtils.isBoolean(currentRowOpts.isFollowSelected)) {
// warnLog('vxe.error.notConflictProp', ['row-config.isCurrent & keyboard-config.isArrow', 'current-row-config.isFollowSelected'])
// }
// if ((columnOpts.isCurrent || highlightCurrentColumn) && props.keyboardConfig && keyboardOpts.isArrow && !XEUtils.isBoolean(currentColumnOpts.isFollowSelected)) {
// warnLog('vxe.error.notConflictProp', ['column-config.isCurrent & keyboard-config.isArrow', 'current-column-config.isFollowSelected'])
// }
// 如果不支持虚拟滚动
// if (props.spanMethod) {
// if (virtualXOpts.enabled) {
// warnLog('vxe.error.notConflictProp', ['span-method', 'virtual-x-config.enabled=false'])
// }
// if (virtualYOpts.enabled) {
// warnLog('vxe.error.notConflictProp', ['span-method', 'virtual-y-config.enabled=false'])
// }
// }
// if (props.footerSpanMethod) {
// if (virtualXOpts.enabled) {
// warnLog('vxe.error.notConflictProp', ['footer-span-method', 'virtual-x-config.enabled=false'])
// }
// }
// 检查是否有安装需要的模块
// if (props.editConfig && !$xeTable.insert) {
// errLog('vxe.error.reqModule', ['Edit'])
// }
// if (props.editRules && !$xeTable.validate) {
// errLog('vxe.error.reqModule', ['Validator'])
// }
// if ((checkboxOpts.range || props.keyboardConfig || props.mouseConfig) && !$xeTable.handleCellMousedownEvent) {
// errLog('vxe.error.reqModule', ['Keyboard'])
// }
// if ((props.printConfig || props.importConfig || props.exportConfig) && !$xeTable.exportData) {
// errLog('vxe.error.reqModule', ['Export'])
// }
Object.assign(scrollYStore, {
startIndex: 0,
endIndex: 0,
visibleSize: 0
});
Object.assign(scrollXStore, {
startIndex: 0,
endIndex: 0,
visibleSize: 0
});
handleUpdateRowGroup(groupFields);
initData();
nextTick(() => {
if (props.autoResize) {
const el = refElem.value;
const parentEl = $xeTable.getParentElem();
resizeObserver = globalResize.create(() => {
if (props.autoResize) {
handleResizeEvent();
}
});
if (el) {
resizeObserver.observe(el);
}
if (parentEl) {
resizeObserver.observe(parentEl);
}
}
});
if (virtualYOpts.mode !== 'scroll') {
const tableViewportEl = refTableViewportElem.value;
if (tableViewportEl) {
tableViewportEl.addEventListener('wheel', $xeTable.triggerBodyWheelEvent, { passive: false });
}
}
globalEvents.on($xeTable, 'paste', handleGlobalPasteEvent);
globalEvents.on($xeTable, 'copy', handleGlobalCopyEvent);
globalEvents.on($xeTable, 'cut', handleGlobalCutEvent);
globalEvents.on($xeTable, 'mousedown', handleGlobalMousedownEvent);
globalEvents.on($xeTable, 'blur', handleGlobalBlurEvent);
globalEvents.on($xeTable, 'mousewheel', handleGlobalMousewheelEvent);
globalEvents.on($xeTable, 'keydown', handleGlobalKeydownEvent);
globalEvents.on($xeTable, 'resize', handleGlobalResizeEvent);
globalEvents.on($xeTable, 'scroll', handleGlobalScrollEvent);
globalEvents.on($xeTable, 'contextmenu', $xeTable.handleGlobalContextmenuEvent);
$xeTable.preventEvent(null, 'mounted', { $table: $xeTable });
});
onBeforeUnmount(() => {
const { _sToTime } = internalData;
if (_sToTime) {
clearTimeout(_sToTime);
}
const tableViewportEl = refTableViewportElem.value;
if (tableViewportEl) {
tableViewportEl.removeEventListener('wheel', $xeTable.triggerBodyWheelEvent);
}
internalData.cvCacheMaps = {};
internalData.prevDragRow = null;
internalData.prevDragCol = null;
if (resizeObserver) {
resizeObserver.disconnect();
}
$xeTable.closeTooltip();
$xeTable.closeFilter();
if ($xeTable.closeMenu) {
$xeTable.closeMenu();
}
globalEvents.off($xeTable, 'paste');
globalEvents.off($xeTable, 'copy');
globalEvents.off($xeTable, 'cut');
globalEvents.off($xeTable, 'mousedown');
globalEvents.off($xeTable, 'blur');
globalEvents.off($xeTable, 'mousewheel');
globalEvents.off($xeTable, 'keydown');
globalEvents.off($xeTable, 'resize');
globalEvents.off($xeTable, 'scroll');
globalEvents.off($xeTable, 'contextmenu');
$xeTable.preventEvent(null, 'beforeUnmount', { $table: $xeTable });
XEUtils.assign(reactData, createReactData());
XEUtils.assign(internalData, createInternalData());
});
onUnmounted(() => {
$xeTable.preventEvent(null, 'unmounted', { $table: $xeTable });
});
nextTick(() => {
const { showOverflow, showHeaderOverflow, showFooterOverflow } = props;
const tooltipOpts = computeTooltipOpts.value;
const headerTooltipOpts = computeHeaderTooltipOpts.value;
const footerTooltipOpts = computeFooterTooltipOpts.value;
if (props.loading) {
if (!VxeUILoadingComponent && !slots.loading) {
errLog('vxe.error.reqComp', ['vxe-loading']);
errLog('vxe.error.errProp', ['loading=true', 'loading=false | <template #loading>...</template>']);
}
}
if (!VxeUITooltipComponent) {
let useOvTip = false;
if (showOverflow === 'tooltip') {
useOvTip = true;
errLog('vxe.error.errProp', ['show-overflow=' + showOverflow, 'show-overflow=false,title,ellipsis']);
}
if (showOverflow === true && tooltipOpts.mode === 'tooltip') {
useOvTip = true;
errLog('vxe.error.notSupportProp', ['show-overflow=' + showOverflow, 'tooltip-config.mode=tooltip', 'tooltip-config.mode=title,ellipsis']);
}
if (showHeaderOverflow === 'tooltip') {
useOvTip = true;
errLog('vxe.error.errProp', ['show-header-overflow=' + showHeaderOverflow, 'show-header-overflow=false,title,ellipsis']);
}
if (showHeaderOverflow === true && headerTooltipOpts.mode === 'tooltip') {
useOvTip = true;
errLog('vxe.error.notSupportProp', ['show-header-overflow=' + showHeaderOverflow, 'header-tooltip-config.mode=tooltip', 'header-tooltip-config.mode=title,ellipsis']);
}
if (showFooterOverflow === 'tooltip') {
useOvTip = true;
errLog('vxe.error.errProp', ['show-footer-overflow=' + showFooterOverflow, 'show-footer-overflow=false,title,ellipsis']);
}
if (showFooterOverflow === true && footerTooltipOpts.mode === 'tooltip') {
useOvTip = true;
errLog('vxe.error.notSupportProp', ['show-footer-overflow=' + showFooterOverflow, 'footer-tooltip-config.mode=tooltip', 'footer-tooltip-config.mode=title,ellipsis']);
}
if (useOvTip) {
errLog('vxe.error.reqComp', ['vxe-tooltip']);
}
}
});
provide('$xeColgroup', null);
provide('$xeTable', $xeTable);
$xeTable.renderVN = renderVN;
return $xeTable;
},
render() {
return this.renderVN();
}
});