import { CreateElement } from 'vue' import XEUtils from 'xe-utils' import { getFuncText, isEnableConf } from '../../ui/src/utils' import { initTpImg } from '../../ui/src/dom' import { createInternalData, createHandleGetRowId, getCellHeight, hasDeepKey } from './util' import { VxeUI } from '../../ui' import methods from './methods' import TableBodyComponent from './body' import TableHeaderComponent from './header' import TableFooterComponent from './footer' import { tableProps } from './props' import { getSlotVNs } from '../../ui/src/vn' import { warnLog, errLog } from '../../ui/src/log' 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 filterMixin from '../module/filter/mixin' import menuMixin from '../module/menu/mixin' import editMixin from '../module/edit/mixin' import exportMixin from '../module/export/mixin' import keyboardMixin from '../module/keyboard/mixin' import validatorMixin from '../module/validator/mixin' import customMixin from '../module/custom/mixin' import type { VxeTabsConstructor, VxeTabsPrivateMethods } from 'vxe-pc-ui' import type { VxeTableConstructor, VxeTablePrivateMethods, VxeTablePropTypes, TableInternalData, TableReactData, VxeTableDefines } from '../../../types' const { getConfig, getIcon, getI18n, renderer, globalResize, globalEvents, globalMixins, renderEmptyElement } = VxeUI function handleUpdateMergeBodyCells ($xeTable: VxeTableConstructor & VxeTablePrivateMethods, merges: VxeTableDefines.MergeOptions | VxeTableDefines.MergeOptions[]) { const internalData = $xeTable as unknown as TableInternalData internalData.mergeBodyList = [] internalData.mergeBodyMaps = {} internalData.mergeBodyCellMaps = {} $xeTable.setMergeCells(merges) } function handleUpdateMergeFooterCells ($xeTable: VxeTableConstructor & VxeTablePrivateMethods, merges: VxeTableDefines.MergeOptions | VxeTableDefines.MergeOptions[]) { const internalData = $xeTable as unknown as TableInternalData internalData.mergeFooterList = [] internalData.mergeFooterMaps = {} internalData.mergeFooterCellMaps = {} $xeTable.setMergeFooterItems(merges) } function handleKeyField ($xeTable: VxeTableConstructor & VxeTablePrivateMethods) { const internalData = $xeTable as unknown as TableInternalData const keyField = $xeTable.computeRowField internalData.currKeyField = keyField internalData.isCurrDeepKey = hasDeepKey(keyField) } /** * 渲染浮固定列 * 分别渲染左边固定列和右边固定列 * 如果宽度足够情况下,则不需要渲染固定列 */ function renderFixed (h: CreateElement, $xeTable: VxeTableConstructor & VxeTablePrivateMethods, fixedType: any) { const props = $xeTable const reactData = $xeTable as unknown as TableReactData const { showHeader, showFooter } = props const { tableData, tableColumn, tableGroupColumn, columnStore, footerTableData } = reactData const isFixedLeft = fixedType === 'left' const fixedColumn = isFixedLeft ? columnStore.leftList : columnStore.rightList return h('div', { ref: isFixedLeft ? 'refLeftContainer' : 'refRightContainer', class: `vxe-table--fixed-${fixedType}-wrapper` }, [ showHeader ? h(TableHeaderComponent, { props: { fixedType, tableData, tableColumn, tableGroupColumn, fixedColumn }, ref: `${fixedType}Header` }) : renderEmptyElement($xeTable), h(TableBodyComponent, { props: { fixedType, tableData, tableColumn, fixedColumn }, ref: `${fixedType}Body` }), showFooter ? h(TableFooterComponent, { props: { footerTableData, tableColumn, fixedColumn, fixedType }, ref: `${fixedType}Footer` }) : renderEmptyElement($xeTable) ]) } function renderEmptyBody (h: CreateElement, $xeTable: VxeTableConstructor & VxeTablePrivateMethods) { const slots = $xeTable.$scopedSlots const $xeGrid = $xeTable.$xeGrid const emptyOpts = $xeTable.computeEmptyOpts const emptySlot = slots.empty let emptyContent: any = '' const emptyParams = { $table: $xeTable, $grid: $xeGrid } if (emptySlot) { emptyContent = emptySlot.call($xeTable, emptyParams) } else { const compConf = emptyOpts.name ? renderer.get(emptyOpts.name) : null const rtEmptyView = compConf ? (compConf.renderTableEmpty || compConf.renderTableEmptyView || compConf.renderEmpty) : null if (rtEmptyView) { emptyContent = getSlotVNs(rtEmptyView.call($xeTable, h, emptyOpts, emptyParams)) } else { emptyContent = getFuncText($xeTable.emptyText) || getI18n('vxe.table.emptyText') } } return emptyContent } const renderDragTipContents = (h: CreateElement, $xeTable: VxeTableConstructor & VxeTablePrivateMethods) => { const props = $xeTable const reactData = $xeTable as unknown as TableReactData const { dragConfig } = props const { dragRow, dragCol, dragTipText } = reactData const columnDragOpts = $xeTable.computeColumnDragOpts const rowDragOpts = $xeTable.computeRowDragOpts const rowDragSlots = rowDragOpts.slots || {} const rTipSlot = rowDragSlots.tip || (dragConfig && dragConfig.slots ? dragConfig.slots.rowTip : null) const columnDragSlots = columnDragOpts.slots || {} const cTipSlot = columnDragSlots.tip if (dragRow && rTipSlot) { return $xeTable.callSlot(rTipSlot, { row: dragRow }, h) } if (dragCol && cTipSlot) { return $xeTable.callSlot(cTipSlot, { column: dragCol }, h) } return [h('span', dragTipText)] } const renderDragTip = (h: CreateElement, $xeTable: VxeTableConstructor & VxeTablePrivateMethods) => { const reactData = $xeTable as unknown as TableReactData const { dragRow, dragCol } = reactData const rowOpts = $xeTable.computeRowOpts const columnOpts = $xeTable.computeColumnOpts const rowDragOpts = $xeTable.computeRowDragOpts const columnDragOpts = $xeTable.computeColumnDragOpts 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 }] }), (dragRow && 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', dragRow ? 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(h, $xeTable)) ]) ]) : renderEmptyElement($xeTable) ]) } return renderEmptyElement($xeTable) } function handleUpdateResize ($xeTable: VxeTableConstructor & VxeTablePrivateMethods) { const el = $xeTable.$refs.refElem as HTMLDivElement if (el && el.clientWidth && el.clientHeight) { $xeTable.recalculate() } } function renderRowExpandedVNs (h: CreateElement, $xeTable: VxeTableConstructor & VxeTablePrivateMethods) { const props = $xeTable const reactData = $xeTable as unknown as TableReactData const internalData = $xeTable as unknown as TableInternalData const $xeGrid = $xeTable.$xeGrid const { treeConfig } = props const { expandColumn, isRowGroupStatus } = reactData const tableRowExpandedList: any[] = ($xeTable as any).computeTableRowExpandedList const expandOpts = $xeTable.computeExpandOpts 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 = $xeTable.computeExpandOpts const { height: expandHeight, padding, indent } = expandOpts const { fullAllDataRowIdData, fullColumnIdData } = internalData const treeOpts = $xeTable.computeTreeOpts const { transform, seqMode } = treeOpts const cellStyle: Record = {} const rowid = handleGetRowId(row) const rowRest = fullAllDataRowIdData[rowid] const colid = expandColumn.id const colRest = fullColumnIdData[colid] || {} let rowLevel = 0 let seq: string | number = -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: VxeTableDefines.CellRenderDataParams = { $grid: $xeGrid, $table: $xeTable, seq, column: expandColumn, columnIndex, $columnIndex, _columnIndex, fixed: '', 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 }], attrs: { rowid }, style: cellStyle }, expandColumn.renderData(h, expandParams)) ) }) } return h('div', { ref: 'refRowExpandElem', class: 'vxe-table--row-expanded-wrapper' }, expandVNs) } function renderScrollX (h: CreateElement, $xeTable: VxeTableConstructor & VxeTablePrivateMethods) { 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', on: { scroll: $xeTable.triggerVirtualScrollXEvent } }, [ h('div', { ref: 'refScrollXSpaceElem', class: 'vxe-table--scroll-x-space' }) ]) ]), h('div', { ref: 'refScrollXRightCornerElem', class: 'vxe-table--scroll-x-right-corner' }) ]) } function renderScrollY (h: CreateElement, $xeTable: VxeTableConstructor & VxeTablePrivateMethods) { 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', on: { scroll: $xeTable.triggerVirtualScrollYEvent } }, [ h('div', { ref: 'refScrollYSpaceElem', class: 'vxe-table--scroll-y-space' }) ]) ]), h('div', { ref: 'refScrollYBottomCornerElem', class: 'vxe-table--scroll-y-bottom-corner' }) ]) } function renderViewport (h: CreateElement, $xeTable: VxeTableConstructor & VxeTablePrivateMethods) { const props = $xeTable const reactData = $xeTable as unknown as TableReactData const { showHeader, showFooter } = props const { overflowX, tableData, tableColumn, tableGroupColumn, footerTableData, columnStore } = reactData const { leftList, rightList } = columnStore return h('div', { ref: 'refTableViewportElem', class: 'vxe-table--viewport-wrapper' }, [ h('div', { class: 'vxe-table--main-wrapper' }, [ /** * 表头 */ showHeader ? h(TableHeaderComponent, { ref: 'refTableHeader', props: { tableData, tableColumn, tableGroupColumn } }) : renderEmptyElement($xeTable), /** * 表体 */ h(TableBodyComponent, { ref: 'refTableBody', props: { tableData, tableColumn } }), /** * 表尾 */ showFooter ? h(TableFooterComponent, { ref: 'refTableFooter', props: { footerTableData, tableColumn } }) : renderEmptyElement($xeTable) ]), h('div', { class: 'vxe-table--fixed-wrapper' }, [ leftList && leftList.length && overflowX ? renderFixed(h, $xeTable, 'left') : renderEmptyElement($xeTable), rightList && rightList.length && overflowX ? renderFixed(h, $xeTable, 'right') : renderEmptyElement($xeTable) ]), renderRowExpandedVNs(h, $xeTable) ]) } function renderBody (h: CreateElement, $xeTable: VxeTableConstructor & VxeTablePrivateMethods) { const scrollbarYToLeft = $xeTable.computeScrollbarYToLeft return h('div', { class: 'vxe-table--layout-wrapper' }, scrollbarYToLeft ? [ renderScrollY(h, $xeTable), renderViewport(h, $xeTable) ] : [ renderViewport(h, $xeTable), renderScrollY(h, $xeTable) ]) } export default { name: 'VxeTable', mixins: [ globalMixins.sizeMixin, filterMixin, menuMixin, editMixin, exportMixin, keyboardMixin, validatorMixin, customMixin ], props: tableProps, provide () { return { $xeTable: this, xecolgroup: null } }, inject: { $xeTabs: { default: null }, $xeGrid: { default: null } }, data () { const xID = XEUtils.uniqueId() return { xID, tId: xID, // 低性能的静态列 staticColumns: [], // 渲染的列分组 tableGroupColumn: [], // 可视区渲染的列 tableColumn: [], // 渲染中的数据 tableData: [], // 是否启用了横向 X 可视渲染方式加载 scrollXLoad: false, // 是否启用了纵向 Y 可视渲染方式加载 scrollYLoad: false, // 是否存在纵向滚动条 overflowY: true, // 是否存在横向滚动条 overflowX: false, // 纵向滚动条的宽度 scrollbarWidth: 0, // 横向滚动条的高度 scrollbarHeight: 0, // 行高 rowHeight: 0, // 表格父容器的高度 parentHeight: 0, // 是否使用分组表头 isGroup: false, isAllOverflow: false, // 复选框属性,是否全选 isAllSelected: false, // 复选框属性,有选中且非全选状态 isIndeterminate: false, // 当前行 currentRow: null, // 单选框属性,选中列 currentColumn: null, // 单选框属性,选中行 selectRadioRow: null, // 表尾合计数据 footerTableData: [], // 行分组列信息 rowGroupColumn: null, // 展开列信息 expandColumn: null, checkboxColumn: null, radioColumn: null, hasFixedColumn: false, // 树节点列信息 treeNodeColumn: null, // 初始化标识 initStore: { filter: false, import: false, export: false, custom: false }, customColumnList: [], // 刷新列标识,当列筛选被改变时,触发表格刷新数据 upDataFlag: 0, // 刷新列标识,当列的特定属性被改变时,触发表格刷新列 reColumnFlag: 0, // 自定义列相关的信息 customStore: { btnEl: null, isAll: false, isIndeterminate: false, activeBtn: false, activeWrapper: false, visible: false, maxHeight: 0, oldSortMaps: {}, oldFixedMaps: {}, oldVisibleMaps: {} }, // 当前选中的筛选列 filterStore: { isAllSelected: false, isIndeterminate: false, style: null, options: [], column: null, multiple: false, visible: false, maxHeight: null }, // 存放列相关的信息 columnStore: { leftList: [], centerList: [], rightList: [], resizeList: [], pxList: [], pxMinList: [], autoMinList: [], scaleList: [], scaleMinList: [], autoList: [], remainList: [] }, // 存放快捷菜单的信息 ctxMenuStore: { selected: null, visible: false, showChild: false, selectChild: null, list: [], style: null }, // 存放可编辑相关信息 editStore: { indexs: { columns: [] }, titles: { columns: [] }, // 选中源 selected: { row: null, column: null }, // 已复制源 copyed: { cut: false, rows: [], columns: [] }, // 激活 actived: { row: null, column: null }, // 当前被强制聚焦单元格,只会在鼠标点击后算聚焦 focused: { row: null, column: null } }, // 存放 tooltip 相关信息 tooltipStore: { row: null, column: null, visible: false, currOpts: {} }, // 存放数据校验相关信息 validStore: { visible: false }, validErrorMaps: {}, // 导入相关信息 importStore: { inited: false, file: null, type: '', modeList: [], typeList: [], filename: '', visible: false }, importParams: { mode: '', types: null, message: true }, // 导出相关信息 exportStore: { inited: false, name: '', modeList: [], typeList: [], columns: [], isPrint: false, hasFooter: false, hasTree: false, hasMerge: false, hasColgroup: false, visible: false }, exportParams: { filename: '', sheetName: '', mode: '', type: '', isColgroup: false, isMerge: false, isAllExpand: false, useStyle: false, original: false, message: true, isHeader: false, isTitle: false, isFooter: false }, visiblwRowsFlag: 1, isRowGroupStatus: false, rowGroupList: [], aggHandleFields: [], aggHandleAggColumns: [], rowGroupExpandedFlag: 1, rowExpandedFlag: 1, treeExpandedFlag: 1, updateCheckboxFlag: 1, pendingRowFlag: 1, insertRowFlag: 1, removeRowFlag: 1, mergeBodyFlag: 1, mergeFootFlag: 1, rowHeightStore: { large: 52, default: 48, medium: 44, small: 40, mini: 36 }, scrollVMLoading: false, scrollYHeight: 0, scrollYTop: 0, isScrollYBig: false, scrollXLeft: 0, scrollXWidth: 0, isScrollXBig: false, rowExpandHeightFlag: 1, calcCellHeightFlag: 1, resizeHeightFlag: 1, resizeWidthFlag: 1, isCustomStatus: false, isDragRowMove: false, dragRow: null, isDragColMove: false, dragCol: null, dragTipText: '', isDragResize: false, isRowLoading: false, isColLoading: false, reScrollFlag: 0, reLayoutFlag: 0, footFlag: 0 } }, computed: { ...({} as { $xeTabs(): (VxeTabsConstructor & VxeTabsPrivateMethods) | null }), tableId () { return this.computeTableId }, computeTableId () { const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods const props = $xeTable const $xeGrid = $xeTable.$xeGrid const { id } = props if (id) { if (XEUtils.isFunction(id)) { return `${id({ $table: $xeTable, $grid: $xeGrid }) || ''}` } return `${id}` } return '' }, computeRowField () { const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods const props = $xeTable const rowOpts = $xeTable.computeRowOpts return `${props.rowId || rowOpts.keyField || '_X_ROW_KEY'}` }, validOpts () { return this.computeValidOpts }, computeValidOpts () { const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods const props = $xeTable return Object.assign({}, getConfig().table.validConfig, props.validConfig) }, sXOpts () { return this.computeVirtualXOpts }, computeSXOpts () { return this.computeVirtualXOpts }, computeScrollXThreshold () { const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods const virtualXOpts = $xeTable.computeVirtualXOpts const { threshold } = virtualXOpts if (threshold) { return XEUtils.toNumber(threshold) } return 0 }, sYOpts () { return this.computeVirtualYOpts }, computeSYOpts () { return this.computeVirtualYOpts }, computeVirtualXOpts () { const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods const props = $xeTable const { virtualXConfig, scrollX } = props const globalVirtualXConfig = getConfig().table.virtualXConfig const globalScrollX = getConfig().table.scrollX if (virtualXConfig) { return Object.assign({}, globalVirtualXConfig, virtualXConfig) as VxeTablePropTypes.VirtualXConfig & { gt: number } } if (scrollX) { // 已废弃,保留兼容 return Object.assign({}, globalScrollX, scrollX) as VxeTablePropTypes.VirtualXConfig & { gt: number } } if (globalVirtualXConfig) { return Object.assign({}, globalVirtualXConfig, virtualXConfig) as VxeTablePropTypes.VirtualXConfig & { gt: number } } // 已废弃,保留兼容 return Object.assign({}, globalScrollX, scrollX) as VxeTablePropTypes.VirtualXConfig & { gt: number } }, computeVirtualYOpts () { const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods const props = $xeTable const { virtualYConfig, scrollY } = props const globalVirtualYConfig = getConfig().table.virtualYConfig const globalScrollY = getConfig().table.scrollY if (virtualYConfig) { return Object.assign({}, globalVirtualYConfig, virtualYConfig) as VxeTablePropTypes.VirtualYConfig & { gt: number } } if (scrollY) { // 已废弃,保留兼容 return Object.assign({}, globalScrollY, scrollY) as VxeTablePropTypes.VirtualYConfig & { gt: number } } if (globalVirtualYConfig) { return Object.assign({}, globalVirtualYConfig, virtualYConfig) as VxeTablePropTypes.VirtualYConfig & { gt: number } } // 已废弃,保留兼容 return Object.assign({}, globalScrollY, scrollY) as VxeTablePropTypes.VirtualYConfig & { gt: number } }, computeScrollbarOpts () { const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods const props = $xeTable return Object.assign({}, getConfig().table.scrollbarConfig, props.scrollbarConfig) }, computeScrollbarXToTop () { const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods const scrollbarOpts = $xeTable.computeScrollbarOpts return !!(scrollbarOpts.x && scrollbarOpts.x.position === 'top') }, computeScrollbarYToLeft () { const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods const scrollbarOpts = $xeTable.computeScrollbarOpts return !!(scrollbarOpts.y && scrollbarOpts.y.position === 'left') }, computeScrollYThreshold () { const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods const virtualYOpts = $xeTable.computeVirtualYOpts const { threshold } = virtualYOpts if (threshold) { return XEUtils.toNumber(threshold) } return 0 }, rowHeightMaps () { return this.computeRowHeightMaps }, computeRowHeightMaps () { const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods const reactData = $xeTable as unknown as TableReactData return reactData.rowHeightStore }, computeDefaultRowHeight () { const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods const vSize = $xeTable.computeSize const rowHeightMaps = $xeTable.computeRowHeightMaps return rowHeightMaps[vSize || 'default'] || 18 }, columnOpts () { return this.computeColumnOpts }, computeColumnOpts () { const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods const props = $xeTable return Object.assign({}, getConfig().table.columnConfig, props.columnConfig) }, computeCurrentColumnOpts () { const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods const props = $xeTable return Object.assign({}, getConfig().table.currentColumnConfig, props.currentColumnConfig) }, computeCellOpts () { const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods const props = $xeTable const cellOpts = Object.assign({}, getConfig().table.cellConfig, props.cellConfig) if (cellOpts.height) { cellOpts.height = XEUtils.toNumber(cellOpts.height) } return cellOpts }, computeHeaderCellOpts () { const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods const props = $xeTable const headerCellOpts = Object.assign({}, getConfig().table.headerCellConfig, props.headerCellConfig) const cellOpts = $xeTable.computeCellOpts headerCellOpts.height = XEUtils.toNumber(getCellHeight(headerCellOpts.height || cellOpts.height)) return headerCellOpts }, computeFooterCellOpts () { const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods const props = $xeTable const footerCellOpts = Object.assign({}, getConfig().table.footerCellConfig, props.footerCellConfig) const cellOpts = $xeTable.computeCellOpts footerCellOpts.height = XEUtils.toNumber(getCellHeight(footerCellOpts.height || cellOpts.height)) return footerCellOpts }, rowOpts () { return this.computeRowOpts }, computeRowOpts () { const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods const props = $xeTable return Object.assign({}, getConfig().table.rowConfig, props.rowConfig) }, computeAggregateOpts () { const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods const props = $xeTable return Object.assign({}, getConfig().table.aggregateConfig || getConfig().table.rowGroupConfig, props.aggregateConfig || props.rowGroupConfig) }, computeRowGroupOpts () { const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods return $xeTable.computeAggregateOpts }, computeCurrentRowOpts () { const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods const props = $xeTable return Object.assign({}, getConfig().table.currentRowConfig, props.currentRowConfig) }, computeRowDragOpts () { const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods const props = $xeTable return Object.assign({}, getConfig().table.rowDragConfig, props.rowDragConfig) }, computeColumnDragOpts () { const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods const props = $xeTable return Object.assign({}, getConfig().table.columnDragConfig, props.columnDragConfig) }, resizeOpts () { return this.computeResizeOpts }, computeResizeOpts () { const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods const props = $xeTable return Object.assign({}, getConfig().table.resizeConfig, props.resizeConfig) }, resizableOpts () { return this.computeResizableOpts }, computeResizableOpts () { const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods const props = $xeTable return Object.assign({}, getConfig().table.resizableConfig, props.resizableConfig) }, seqOpts () { return this.computeSeqOpts }, computeSeqOpts () { const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods const props = $xeTable return Object.assign({ startIndex: 0 }, getConfig().table.seqConfig, props.seqConfig) }, radioOpts () { return this.computeRadioOpts }, computeRadioOpts () { const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods const props = $xeTable return Object.assign({}, getConfig().table.radioConfig, props.radioConfig) }, checkboxOpts () { return this.computeCheckboxOpts }, computeCheckboxOpts () { const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods const props = $xeTable return Object.assign({}, getConfig().table.checkboxConfig, props.checkboxConfig) }, tooltipOpts () { return this.computeTooltipOpts }, computeTooltipOpts () { const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods const props = $xeTable return Object.assign({}, getConfig().tooltip, getConfig().table.tooltipConfig, props.tooltipConfig) }, tipConfig () { return { ...this.tooltipOpts } }, computeTableTipConfig () { const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods const reactData = $xeTable as unknown as TableReactData const { tooltipStore } = reactData const tooltipOpts = $xeTable.computeTooltipOpts return Object.assign({}, tooltipOpts, tooltipStore.currOpts) }, computeValidTipConfig () { const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods const tooltipOpts = $xeTable.computeTooltipOpts return Object.assign({}, tooltipOpts) }, validTipOpts () { return Object.assign({ isArrow: false }, this.tooltipOpts) }, editOpts () { return this.computeEditOpts }, computeEditOpts () { return Object.assign({}, getConfig().table.editConfig, this.editConfig) }, sortOpts () { return this.computeSortOpts }, computeSortOpts () { return Object.assign({ orders: ['asc', 'desc', null] }, getConfig().table.sortConfig, this.sortConfig) }, filterOpts () { return this.computeFilterOpts }, computeFilterOpts () { return Object.assign({}, getConfig().table.filterConfig, this.filterConfig) }, mouseOpts () { return this.computeMouseOpts }, computeMouseOpts () { return Object.assign({}, getConfig().table.mouseConfig, this.mouseConfig) }, areaOpts () { return this.computeAreaOpts }, computeAreaOpts () { return Object.assign({}, getConfig().table.areaConfig, this.areaConfig) }, keyboardOpts () { return this.computeKeyboardOpts }, computeKeyboardOpts () { return Object.assign({}, getConfig().table.keyboardConfig, this.keyboardConfig) }, clipOpts () { return this.computeClipOpts }, computeClipOpts () { return Object.assign({}, getConfig().table.clipConfig, this.clipConfig) }, fnrOpts () { return this.computeFnrOpts }, computeFNROpts () { return this.computeFnrOpts }, computeFnrOpts () { return Object.assign({}, getConfig().table.fnrConfig, this.fnrConfig) }, headerCtxMenu () { return this.computeHeaderMenu }, computeHeaderMenu () { const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods const menuOpts = $xeTable.computeMenuOpts const headerOpts = menuOpts.header return headerOpts && headerOpts.options ? headerOpts.options : [] }, bodyCtxMenu () { return this.computeBodyMenu }, computeBodyMenu () { const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods const menuOpts = $xeTable.computeMenuOpts const bodyOpts = menuOpts.body return bodyOpts && bodyOpts.options ? bodyOpts.options : [] }, footerCtxMenu () { return this.computeFooterMenu }, computeFooterMenu () { const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods const menuOpts = $xeTable.computeMenuOpts const footerOpts = menuOpts.footer return footerOpts && footerOpts.options ? footerOpts.options : [] }, isCtxMenu () { return this.computeIsMenu }, computeIsMenu () { const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods const props = $xeTable const menuOpts = $xeTable.computeMenuOpts const headerMenu = $xeTable.computeHeaderMenu const bodyMenu = $xeTable.computeBodyMenu const footerMenu = $xeTable.computeFooterMenu return !!(((props as any).contextMenu || props.menuConfig) && isEnableConf(menuOpts) && (headerMenu.length || bodyMenu.length || footerMenu.length)) }, ctxMenuList () { return this.computeMenuList }, computeMenuList () { const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods const reactData = $xeTable as unknown as TableReactData const { ctxMenuStore } = reactData const rest: any[] = [] ctxMenuStore.list.forEach((list) => { list.forEach((item) => { rest.push(item) }) }) return rest }, ctxMenuOpts () { return this.computeMenuOpts }, computeMenuOpts () { return Object.assign({}, getConfig().table.menuConfig, this.contextMenu, this.menuConfig) }, computeLeftFixedWidth () { const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods const reactData = $xeTable as unknown as TableReactData 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 }, computeRightFixedWidth () { const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods const reactData = $xeTable as unknown as TableReactData 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 }, exportOpts () { return this.computeExportOpts }, computeExportOpts () { return Object.assign({}, getConfig().table.exportConfig, this.exportConfig) }, importOpts () { return this.computeImportOpts }, computeImportOpts () { return Object.assign({}, getConfig().table.importConfig, this.importConfig) }, printOpts () { return this.computePrintOpts }, computePrintOpts () { return Object.assign({}, getConfig().table.printConfig, this.printConfig) }, expandOpts () { return this.computeExpandOpts }, computeExpandOpts () { return Object.assign({}, getConfig().table.expandConfig, this.expandConfig) }, treeOpts () { return this.computeTreeOpts }, computeTreeOpts () { return Object.assign({}, getConfig().table.treeConfig, this.treeConfig) }, emptyOpts () { return this.computeEmptyOpts }, computeEmptyOpts () { return Object.assign({}, getConfig().table.emptyRender, this.emptyRender) }, loadingOpts () { return this.computeLoadingOpts }, computeLoadingOpts () { return Object.assign({}, getConfig().table.loadingConfig, this.loadingConfig) }, computeCellOffsetWidth () { return this.border ? Math.max(2, Math.ceil(this.scrollbarWidth / this.tableColumn.length)) : 1 }, customOpts () { return this.computeCustomOpts }, computeCustomOpts () { return Object.assign({}, getConfig().table.customConfig, this.customConfig) }, computeTableRowExpandedList () { const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods const reactData = $xeTable as unknown as TableReactData const internalData = $xeTable as unknown as TableInternalData const { tableData, rowExpandedFlag, expandColumn, rowGroupExpandedFlag, treeExpandedFlag } = reactData const { visibleDataRowIdData, rowExpandedMaps } = internalData const expandList: any[] = [] if (tableData.length && expandColumn && rowExpandedFlag && rowGroupExpandedFlag && treeExpandedFlag) { XEUtils.each(rowExpandedMaps, (row, rowid) => { if (visibleDataRowIdData[rowid]) { expandList.push(row) } }) } return expandList }, computeAutoWidthColumnList () { const { tableColumn, visibleColumn } = this return tableColumn.length || visibleColumn.length ? visibleColumn.filter((column: any) => column.width === 'auto' || column.minWidth === 'auto') : [] }, computeFixedColumnSize () { const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods const reactData = $xeTable as unknown as TableReactData const internalData = $xeTable as unknown as TableInternalData const { tableColumn } = reactData const { collectColumn } = internalData let fixedSize = 0 // 只判断第一层 if (tableColumn.length && collectColumn.length) { collectColumn.forEach((column: any) => { if (column.renderFixed) { fixedSize++ } }) } return fixedSize }, fixedColumnSize () { const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods return $xeTable.computeFixedColumnSize }, computeIsMaxFixedColumn () { const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods const fixedColumnSize = $xeTable.computeFixedColumnSize const columnOpts = $xeTable.columnOpts const { maxFixedSize } = columnOpts if (maxFixedSize) { return fixedColumnSize >= maxFixedSize } return false }, computeTableBorder () { const $xeTable = this const props = $xeTable const { border } = props if (border === true) { return 'full' } if (border) { return border } return 'default' }, /** * 判断列全选的复选框是否禁用 */ isAllCheckboxDisabled () { const { tableFullData, tableData, treeConfig, checkboxOpts } = this const { strict, checkMethod } = checkboxOpts if (strict) { if (tableData.length || tableFullData.length) { if (checkMethod) { if (treeConfig) { // 暂时不支持树形结构 } // 如果所有行都被禁用 return tableFullData.every((row: any) => !checkMethod({ row })) } return false } return true } return false }, computeVirtualScrollBars () { const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods const reactData = $xeTable as unknown as TableReactData const { overflowX, scrollXLoad, overflowY, scrollYLoad } = reactData return { x: overflowX && scrollXLoad, y: overflowY && scrollYLoad } }, computeRowGroupFields () { const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods const aggregateOpts = $xeTable.computeAggregateOpts return aggregateOpts.groupFields }, computeRowGroupColumns () { const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods const reactData = $xeTable as unknown as TableReactData const internalData = $xeTable as unknown as TableInternalData const { rowGroupList } = reactData const { fullColumnFieldData } = internalData const rgColumns: VxeTableDefines.ColumnInfo[] = [] rowGroupList.forEach(aggConf => { const colRest = fullColumnFieldData[aggConf.field] if (colRest) { rgColumns.push(colRest.column) } }) return rgColumns }, tabsResizeFlag () { const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods const $xeTabs = $xeTable.$xeTabs return $xeTabs ? $xeTabs.reactData.resizeFlag : null }, computeVxeLanguage () { return VxeUI.getLanguage() } } as any, watch: { data (value: any) { const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods const reactData = $xeTable as unknown as TableReactData const { initStatus } = this if (value && value.length >= 50000) { warnLog('vxe.error.errLargeData', ['loadData(data), reloadData(data)']) } this.loadTableData(value || [], true).then(() => { const { scrollXLoad, scrollYLoad, expandColumn } = reactData const expandOpts = $xeTable.computeExpandOpts this.inited = true this.initStatus = true if (!initStatus) { this.handleLoadDefaults() } // const checkboxColumn = this.tableFullColumn.find(column => column.type === 'checkbox') // if (checkboxColumn && this.tableFullData.length > 300 && !this.checkboxOpts.checkField) { // warnLog('vxe.error.checkProp', ['checkbox-config.checkField']) // } if ((scrollXLoad || scrollYLoad) && (expandColumn && expandOpts.mode !== 'fixed')) { warnLog('vxe.error.scrollErrProp', ['column.type=expand']) } this.recalculate() }) }, staticColumns (value: any) { this.$nextTick(() => this.handleInitColumn(XEUtils.clone(value))) }, tableColumn () { this.analyColumnWidth() }, upDataFlag () { this.$nextTick().then(() => this.updateData()) }, reColumnFlag () { this.$nextTick().then(() => this.refreshColumn()) }, computeSize () { this.reLayoutFlag++ }, showHeader () { this.reLayoutFlag++ }, showFooter () { this.reLayoutFlag++ }, overflowX () { this.reLayoutFlag++ }, overflowY () { this.reLayoutFlag++ }, height () { this.reLayoutFlag++ }, maxHeight () { this.reLayoutFlag++ }, computeScrollbarXToTop () { this.reLayoutFlag++ }, computeScrollbarYToLeft () { this.reLayoutFlag++ }, computeVxeLanguage () { this.reLayoutFlag++ }, reLayoutFlag () { const $xeTable = this $xeTable.$nextTick(() => $xeTable.recalculate(true)) }, footerData () { this.footFlag++ }, footFlag () { const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods $xeTable.updateFooter() }, syncResize (value: any) { const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods if (value) { handleUpdateResize($xeTable) $xeTable.$nextTick(() => { handleUpdateResize($xeTable) setTimeout(() => handleUpdateResize($xeTable)) }) } }, tabsResizeFlag () { this.handleGlobalResizeEvent() }, mergeCells (value: any) { const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods handleUpdateMergeBodyCells($xeTable, value) }, mergeFooterItems (value: any) { const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods handleUpdateMergeFooterCells($xeTable, value) }, computeRowGroupFields (val: any) { const $xeTable = this $xeTable.handleUpdateRowGroup(val) }, computeRowField () { const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods const reactData = $xeTable as unknown as TableReactData const internalData = $xeTable as unknown as TableInternalData // 行主键被改变,重载表格 const { inited, tableFullData } = internalData if (inited) { handleKeyField($xeTable) reactData.tableData = [] $xeTable.$nextTick(() => { $xeTable.reloadData(tableFullData) }) } } } as any, created () { const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods const props = $xeTable const internalData = $xeTable as unknown as TableInternalData XEUtils.assign(internalData, createInternalData()) handleKeyField($xeTable) const { data, exportConfig, importConfig, treeConfig, showOverflow, highlightCurrentRow, highlightCurrentColumn } = props const { scrollXStore, scrollYStore } = internalData const columnOpts = $xeTable.computeColumnOpts const editOpts = $xeTable.computeEditOpts const treeOpts = $xeTable.computeTreeOpts const radioOpts = $xeTable.computeRadioOpts const checkboxOpts = $xeTable.computeCheckboxOpts const expandOpts = $xeTable.computeExpandOpts const rowOpts = $xeTable.computeRowOpts const customOpts = $xeTable.computeCustomOpts const mouseOpts = $xeTable.computeMouseOpts const exportOpts = $xeTable.computeExportOpts const importOpts = $xeTable.computeImportOpts const currentRowOpts = $xeTable.computeCurrentRowOpts const currentColumnOpts = $xeTable.computeCurrentColumnOpts const keyboardOpts = $xeTable.computeKeyboardOpts const aggregateOpts = $xeTable.computeAggregateOpts const { groupFields } = aggregateOpts 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 (props.editConfig && editOpts.showStatus && !props.keepSource) { warnLog('vxe.error.reqProp', ['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 (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 (this.tooltipOpts.enabled) { warnLog('vxe.error.delProp', ['tooltip-config.enabled', 'tooltip-config.showAll']) } if (this.highlightCurrentRow) { warnLog('vxe.error.delProp', ['highlight-current-row', 'row-config.isCurrent']) } if (this.highlightHoverRow) { warnLog('vxe.error.delProp', ['highlight-hover-row', 'row-config.isHover']) } if (this.highlightCurrentColumn) { warnLog('vxe.error.delProp', ['highlight-current-column', 'column-config.isCurrent']) } if (this.highlightHoverColumn) { warnLog('vxe.error.delProp', ['highlight-hover-column', 'column-config.isHover']) } if (props.resizable) { warnLog('vxe.error.delProp', ['resizable', 'column-config.resizable']) } // 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 (!props.id) { if ((props.customConfig ? isEnableConf(customOpts) : customOpts.enabled) && customOpts.storage) { errLog('vxe.error.reqProp', ['id']) } } if (treeConfig && checkboxOpts.range) { errLog('vxe.error.noTree', ['checkbox-config.range']) } if (rowOpts.height && !this.showOverflow) { warnLog('vxe.error.notProp', ['table.show-overflow']) } if (!$xeTable.triggerCellAreaModownEvent) { 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 (!$xeTable.handlePivotTableAggregateData) { 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) { warnLog('vxe.error.notSupportProp', ['column-config.drag', 'tree-config.transform=false', 'tree-config.transform=true']) } 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.noTree', ['mouse-config.area']) } if (props.editConfig && editOpts.activeMethod) { warnLog('vxe.error.delProp', ['table.edit-config.activeMethod', 'table.edit-config.beforeEditMethod']) } if (props.treeConfig && checkboxOpts.isShiftKey) { errLog('vxe.error.errConflicts', ['tree-config', 'checkbox-config.isShiftKey']) } if (checkboxOpts.halfField) { warnLog('vxe.error.delProp', ['checkbox-config.halfField', 'checkbox-config.indeterminateField']) } // 在 v3.0 中废弃 context-menu if (this.contextMenu) { warnLog('vxe.error.delProp', ['context-menu', 'menu-config']) if (!XEUtils.isObject(this.contextMenu)) { warnLog('vxe.error.errProp', [`table.context-menu=${this.contextMenu}`, 'table.context-menu={}']) } } if (props.menuConfig && !XEUtils.isObject(props.menuConfig)) { warnLog('vxe.error.errProp', [`table.menu-config=${props.menuConfig}`, 'table.menu-config={}']) } if (props.exportConfig && !XEUtils.isObject(props.exportConfig)) { warnLog('vxe.error.errProp', [`table.export-config=${props.exportConfig}`, 'table.export-config={}']) } if (props.importConfig && !XEUtils.isObject(props.importConfig)) { warnLog('vxe.error.errProp', [`table.import-config=${props.importConfig}`, 'table.import-config={}']) } if (props.printConfig && !XEUtils.isObject(props.printConfig)) { warnLog('vxe.error.errProp', [`table.print-config=${props.printConfig}`, 'table.print-config={}']) } if (props.treeConfig && !XEUtils.isObject(props.treeConfig)) { warnLog('vxe.error.errProp', [`table.tree-config=${props.treeConfig}`, 'table.tree-config={}']) } if (props.customConfig && !XEUtils.isObject(props.customConfig)) { warnLog('vxe.error.errProp', [`table.custom-config=${props.customConfig}`, 'table.custom-config={}']) } if (props.editConfig && !XEUtils.isObject(props.editConfig)) { warnLog('vxe.error.errProp', [`table.edit-config=${props.editConfig}`, 'table.edit-config={}']) } if (props.emptyRender && !XEUtils.isObject(props.emptyRender)) { warnLog('vxe.error.errProp', [`table.empty-render=${props.emptyRender}`, 'table.empty-render={}']) } 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', 'current-row-config.isFollowSelected']) } if ((columnOpts.isCurrent || highlightCurrentColumn) && props.keyboardConfig && keyboardOpts.isArrow && !XEUtils.isBoolean(currentColumnOpts.isFollowSelected)) { warnLog('vxe.error.notConflictProp', ['column-config.isCurrent', '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: 1, visibleSize: 0 }) Object.assign(scrollXStore, { startIndex: 0, endIndex: 1, visibleSize: 0 }) this.handleUpdateRowGroup(groupFields) this.loadTableData(data, true).then(() => { if (data && data.length) { this.inited = true this.initStatus = true this.handleLoadDefaults() } this.handleInitDefaults() this.updateStyle() }) globalEvents.on($xeTable, 'paste', this.handleGlobalPasteEvent) globalEvents.on($xeTable, 'copy', this.handleGlobalCopyEvent) globalEvents.on($xeTable, 'cut', this.handleGlobalCutEvent) globalEvents.on($xeTable, 'mousedown', this.handleGlobalMousedownEvent) globalEvents.on($xeTable, 'blur', this.handleGlobalBlurEvent) globalEvents.on($xeTable, 'mousewheel', this.handleGlobalMousewheelEvent) globalEvents.on($xeTable, 'keydown', this.handleGlobalKeydownEvent) globalEvents.on($xeTable, 'resize', this.handleGlobalResizeEvent) globalEvents.on($xeTable, 'contextmenu', this.handleGlobalContextmenuEvent) $xeTable.preventEvent(null, 'created') }, mounted () { const $xeTable = this const props = $xeTable const columnOpts = $xeTable.computeColumnOpts const rowOpts = $xeTable.computeRowOpts const customOpts = $xeTable.computeCustomOpts const virtualYOpts = $xeTable.computeVirtualYOpts if (columnOpts.drag || rowOpts.drag || customOpts.allowSort) { initTpImg() } const { $listeners } = this if (!this.menuConfig && ($listeners['menu-click'] || $listeners['cell-menu'] || $listeners['header-cell-menu'] || $listeners['footer-cell-menu'])) { warnLog('vxe.error.reqProp', ['menu-config']) } if (!this.tooltipConfig && ($listeners['cell-mouseenter'] || $listeners['cell-mouseleave'])) { warnLog('vxe.error.reqProp', ['tooltip-config']) } // 使用已安装的组件,如果未安装则不渲染 const VxeUILoadingComponent = VxeUI.getComponent('VxeLoading') const VxeUITooltipComponent = VxeUI.getComponent('VxeTooltip') $xeTable.$nextTick(() => { if (props.loading) { if (!VxeUILoadingComponent && !this.$scopedSlots.loading) { errLog('vxe.error.errProp', ['loading=true', 'loading=false | ']) errLog('vxe.error.reqComp', ['vxe-loading']) } } if ((props.showOverflow === true || props.showOverflow === 'tooltip') || (props.showHeaderOverflow === true || props.showHeaderOverflow === 'tooltip') || (props.showFooterOverflow === true || props.showFooterOverflow === 'tooltip') || props.tooltipConfig || props.editRules) { if (!VxeUITooltipComponent) { if (props.showOverflow === true) { errLog('vxe.error.errProp', ['show-overflow=true', 'show-overflow=title']) } if (props.showOverflow === 'tooltip') { errLog('vxe.error.errProp', ['show-overflow=tooltip', 'show-overflow=title']) } if (props.showHeaderOverflow === true) { errLog('vxe.error.errProp', ['show-header-overflow=true', 'show-header-overflow=title']) } if (props.showHeaderOverflow === 'tooltip') { errLog('vxe.error.errProp', ['show-header-overflow=tooltip', 'show-header-overflow=title']) } if (props.showFooterOverflow === true) { errLog('vxe.error.errProp', ['show-footer-overflow=true', 'show-footer-overflow=title']) } if (props.showFooterOverflow === 'tooltip') { errLog('vxe.error.errProp', ['show-footer-overflow=tooltip', 'show-footer-overflow=title']) } errLog('vxe.error.reqComp', ['vxe-tooltip']) } } if (this.autoResize) { const resizeObserver = globalResize.create(() => { if (this.autoResize) { this.handleResizeEvent() } }) resizeObserver.observe(this.$el) resizeObserver.observe(this.getParentElem()) this.$resize = resizeObserver } }) if (virtualYOpts.mode !== 'scroll') { const tableViewportEl = $xeTable.$refs.refTableViewportElem as HTMLDivElement if (tableViewportEl) { tableViewportEl.addEventListener('wheel', $xeTable.triggerBodyWheelEvent, { passive: false }) } } $xeTable.preventEvent(null, 'mounted') }, activated () { this.recalculate().then(() => this.refreshScroll()) this.preventEvent(null, 'activated') }, deactivated () { this.preventEvent(null, 'deactivated') }, beforeDestroy () { const $xeTable = this const tableViewportEl = $xeTable.$refs.refTableViewportElem as HTMLDivElement if (tableViewportEl) { tableViewportEl.removeEventListener('wheel', $xeTable.triggerBodyWheelEvent) } if (this.$resize) { this.$resize.disconnect() } this.closeFilter() this.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, 'contextmenu') this.preventEvent(null, 'beforeDestroy') }, destroyed () { const $xeTable = this const internalData = $xeTable as unknown as TableInternalData this.preventEvent(null, 'destroyed') XEUtils.assign(internalData, createInternalData()) }, render (h: CreateElement) { // 使用已安装的组件,如果未安装则不渲染 const VxeUILoadingComponent = VxeUI.getComponent('VxeLoading') const VxeUITooltipComponent = VxeUI.getComponent('VxeTooltip') const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods const $xeGrid = $xeTable.$xeGrid const props = $xeTable const slots = $xeTable.$scopedSlots const reactData = $xeTable as unknown as TableReactData const { xID } = $xeTable 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 } = reactData const { leftList, rightList } = columnStore const loadingSlot = slots.loading const tableTipConfig = $xeTable.computeTableTipConfig const validTipConfig = $xeTable.computeValidTipConfig const validOpts = $xeTable.computeValidOpts const checkboxOpts = $xeTable.computeCheckboxOpts const treeOpts = $xeTable.computeTreeOpts const rowOpts = $xeTable.computeRowOpts const columnOpts = $xeTable.computeColumnOpts const vSize = $xeTable.computeSize const tableBorder = $xeTable.computeTableBorder const mouseOpts = $xeTable.computeMouseOpts const areaOpts = $xeTable.computeAreaOpts const loadingOpts = $xeTable.computeLoadingOpts const isMenu = $xeTable.computeIsMenu const currLoading = reactData.isColLoading || reactData.isRowLoading || loading const resizableOpts = $xeTable.computeResizableOpts const isArea = mouseConfig && mouseOpts.area const columnDragOpts = $xeTable.computeColumnDragOpts const scrollbarXToTop = $xeTable.computeScrollbarXToTop const scrollbarYToLeft = $xeTable.computeScrollbarYToLeft return h('div', { 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, 'is--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, 'is--scroll-x': overflowX, 'is--virtual-x': scrollXLoad, 'is--virtual-y': scrollYLoad }], attrs: { spellcheck: false }, on: { keydown: this.keydownEvent } }, [ /** * 隐藏列 */ h('div', { class: 'vxe-table-slots', ref: 'hideColumn' }, this.$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(h, $xeTable), renderBody(h, $xeTable) ] : [ renderBody(h, $xeTable), renderScrollX(h, $xeTable) ]), /** * 空数据 */ h('div', { key: 'tn', ref: 'refEmptyPlaceholder', class: 'vxe-table--empty-placeholder' }, [ h('div', { class: 'vxe-table--empty-content' }, renderEmptyBody(h, $xeTable)) ]), /** * 边框线 */ 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', { ref: 'refColResizeTip', class: 'vxe-table--resizable-number-tip' }) ] : []), /** * 行高线 */ 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', props: { value: currLoading, icon: loadingOpts.icon, text: loadingOpts.text }, scopedSlots: loadingSlot ? { default: () => $xeTable.callSlot(loadingSlot, { $table: $xeTable, $grid: $xeGrid, loading: currLoading }, h) } : {} }) : loadingSlot ? h('div', { class: ['vxe-loading--custom-wrapper', { 'is--visible': currLoading }] }, $xeTable.callSlot(loadingSlot, { $table: $xeTable, $grid: $xeGrid, loading: currLoading }, h)) : renderEmptyElement($xeTable), /** * 自定义列 */ initStore.custom ? h(TableCustomPanelComponent, { key: 'cs', ref: 'refTableCustom', props: { customStore } }) : renderEmptyElement($xeTable), /** * 筛选 */ initStore.filter ? h(TableFilterPanelComponent, { key: 'tf', ref: 'refTableFilter', props: { filterStore } }) : renderEmptyElement($xeTable), /** * 导入 */ initStore.import && this.importConfig ? h(TableImportPanelComponent, { key: 'it', props: { defaultOptions: this.importParams, storeData: this.importStore } }) : renderEmptyElement($xeTable), /** * 导出 */ initStore.export && (this.exportConfig || this.printConfig) ? h(TableExportPanelComponent, { key: 'et', props: { defaultOptions: this.exportParams, storeData: this.exportStore } }) : renderEmptyElement($xeTable), /** * 快捷菜单 */ isMenu ? h(TableMenuPanelComponent, { key: 'tm', ref: 'refTableMenu', props: { ctxMenuStore: this.ctxMenuStore, ctxMenuOpts: this.ctxMenuOpts } }) : renderEmptyElement($xeTable), /** * 拖拽提示 */ renderDragTip(h, this), h('div', {}, [ /** * 提示相关 */ VxeUITooltipComponent ? h(VxeUITooltipComponent, { key: 'ctp', ref: 'refCommTooltip', props: { isArrow: false, enterable: false } }) : renderEmptyElement($xeTable), /** * 工具提示 */ VxeUITooltipComponent ? h(VxeUITooltipComponent, { key: 'btp', ref: 'refTooltip', props: { theme: tableTipConfig.theme, enterable: tableTipConfig.enterable, enterDelay: tableTipConfig.enterDelay, leaveDelay: tableTipConfig.leaveDelay, useHTML: tableTipConfig.useHTML } }) : renderEmptyElement($xeTable), /** * 校验提示 */ VxeUITooltipComponent && this.editRules && validOpts.showMessage && (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'], props: { theme: validTipConfig.theme, enterable: validTipConfig.enterable, enterDelay: validTipConfig.enterDelay, leaveDelay: validTipConfig.leaveDelay } }) : renderEmptyElement($xeTable) ]) ]) }, methods } as any