diff --git a/examples/views/table/TableTest8.vue b/examples/views/table/TableTest8.vue index 09e0548958..f201f0a24f 100644 --- a/examples/views/table/TableTest8.vue +++ b/examples/views/table/TableTest8.vue @@ -147,7 +147,7 @@ const imgList1CellRender = reactive({ moreConfig: { maxCount: 2 }, - imageStyle: { + imageConfig: { width: 40, height: 40 } diff --git a/examples/views/table/TableTest9.vue b/examples/views/table/TableTest9.vue index 0d407f8c1e..5447520eb2 100644 --- a/examples/views/table/TableTest9.vue +++ b/examples/views/table/TableTest9.vue @@ -144,7 +144,7 @@ const imgList1CellRender = reactive({ moreConfig: { maxCount: 2 }, - imageStyle: { + imageConfig: { width: 40, height: 40 } diff --git a/package.json b/package.json index a489db88ba..0169145cb5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vxe-table", - "version": "4.9.34", + "version": "4.9.35", "description": "一个基于 vue 的 PC 端表格组件,支持增删改查、虚拟树、拖拽排序,懒加载、快捷菜单、数据校验、树形结构、打印、导入导出、自定义模板、渲染器、JSON 配置式...", "scripts": { "update": "npm install --legacy-peer-deps", @@ -28,7 +28,7 @@ "style": "lib/style.css", "typings": "types/index.d.ts", "dependencies": { - "vxe-pc-ui": "^4.3.42" + "vxe-pc-ui": "^4.3.43" }, "devDependencies": { "@types/resize-observer-browser": "^0.1.11", diff --git a/packages/table/render/index.ts b/packages/table/render/index.ts index 9af8c8192e..daf83cb6ce 100644 --- a/packages/table/render/index.ts +++ b/packages/table/render/index.ts @@ -15,6 +15,10 @@ const componentDefaultModelProp = 'modelValue' const defaultCompProps = {} +function handleDefaultValue (value: any, defaultVal: any, initVal: any) { + return XEUtils.eqNull(value) ? (XEUtils.eqNull(defaultVal) ? initVal : defaultVal) : value +} + function parseDate (value: any, props: any) { return value && props.valueFormat ? XEUtils.toStringDate(value, props.valueFormat) : value } @@ -612,13 +616,25 @@ renderer.mixin({ if (cellValue) { const numberInputConfig = getConfig().numberInput || {} if (type === 'float') { - const digits = props.digits || numberInputConfig.digits || 1 + const autoFill = handleDefaultValue(props.autoFill, numberInputConfig.autoFill, true) + const digits = handleDefaultValue(props.digits, numberInputConfig.digits, 1) cellValue = XEUtils.toFixed(XEUtils.floor(cellValue, digits), digits) + if (!autoFill) { + cellValue = XEUtils.toNumber(cellValue) + } } else if (type === 'amount') { - const digits = props.digits || numberInputConfig.digits || 2 + const autoFill = handleDefaultValue(props.autoFill, numberInputConfig.autoFill, true) + const digits = handleDefaultValue(props.digits, numberInputConfig.digits, 2) + const showCurrency = handleDefaultValue(props.showCurrency, numberInputConfig.showCurrency, false) cellValue = XEUtils.commafy(XEUtils.toNumber(cellValue), { digits }) - const showCurrency = props.showCurrency - if (XEUtils.isBoolean(showCurrency) ? showCurrency : numberInputConfig.showCurrency) { + if (!autoFill) { + const [iStr, dStr] = cellValue.split('.') + if (dStr) { + const dRest = dStr.replace(/0+$/, '') + cellValue = dRest ? [iStr, '.', dRest].join('') : iStr + } + } + if (showCurrency) { cellValue = `${props.currencySymbol || numberInputConfig.currencySymbol || getI18n('vxe.numberInput.currencySymbol') || ''}${cellValue}` } } @@ -630,18 +646,36 @@ renderer.mixin({ const { row, column, _columnIndex } = params const { type } = props // 兼容老模式 - const cellValue = XEUtils.isArray(row) ? row[_columnIndex] : XEUtils.get(row, column.field) - if (XEUtils.isNumber(cellValue)) { + const itemValue = XEUtils.isArray(row) ? row[_columnIndex] : XEUtils.get(row, column.field) + if (XEUtils.isNumber(itemValue)) { const numberInputConfig = getConfig().numberInput || {} if (type === 'float') { - const digits = props.digits || numberInputConfig.digits || 1 - return XEUtils.toFixed(XEUtils.floor(cellValue, digits), digits) + const autoFill = handleDefaultValue(props.autoFill, numberInputConfig.autoFill, true) + const digits = handleDefaultValue(props.digits, numberInputConfig.digits, 1) + let amountLabel = XEUtils.toFixed(XEUtils.floor(itemValue, digits), digits) + if (!autoFill) { + amountLabel = XEUtils.toNumber(amountLabel) + } + return amountLabel } else if (type === 'amount') { - const digits = props.digits || numberInputConfig.digits || 2 - return XEUtils.commafy(XEUtils.toNumber(cellValue), { digits }) + const autoFill = handleDefaultValue(props.autoFill, numberInputConfig.autoFill, true) + const digits = handleDefaultValue(props.digits, numberInputConfig.digits, 2) + const showCurrency = handleDefaultValue(props.showCurrency, numberInputConfig.showCurrency, false) + let amountLabel = XEUtils.commafy(XEUtils.toNumber(itemValue), { digits }) + if (!autoFill) { + const [iStr, dStr] = amountLabel.split('.') + if (dStr) { + const dRest = dStr.replace(/0+$/, '') + amountLabel = dRest ? [iStr, '.', dRest].join('') : iStr + } + } + if (showCurrency) { + amountLabel = `${props.currencySymbol || numberInputConfig.currencySymbol || getI18n('vxe.numberInput.currencySymbol') || ''}${amountLabel}` + } + return amountLabel } } - return getFuncText(cellValue, 1) + return getFuncText(itemValue, 1) }, renderTableDefault: defaultEditRender, renderTableFilter: defaultFilterRender, diff --git a/packages/table/src/body.ts b/packages/table/src/body.ts index a5effefa20..a2744c3414 100644 --- a/packages/table/src/body.ts +++ b/packages/table/src/body.ts @@ -1,4 +1,4 @@ -import { createCommentVNode, defineComponent, TransitionGroup, h, ref, Ref, PropType, inject, nextTick, ComputedRef, onBeforeUnmount, onMounted, onUnmounted } from 'vue' +import { defineComponent, TransitionGroup, h, ref, Ref, PropType, inject, nextTick, ComputedRef, onBeforeUnmount, onMounted, onUnmounted } from 'vue' import XEUtils from 'xe-utils' import { VxeUI } from '../../ui' import { mergeBodyMethod, getRowid, getRefElem } from './util' @@ -36,7 +36,7 @@ export default defineComponent({ const { xID, props: tableProps, context: tableContext, reactData: tableReactData, internalData: tableInternalData } = $xeTable const { refTableBody, refTableHeader, refTableFooter, refTableLeftBody, refTableRightBody, refScrollXHandleElem, refScrollYHandleElem } = $xeTable.getRefMaps() - const { computeEditOpts, computeMouseOpts, computeAreaOpts, computeSYOpts, computeEmptyOpts, computeKeyboardOpts, computeTooltipOpts, computeRadioOpts, computeExpandOpts, computeTreeOpts, computeCheckboxOpts, computeCellOpts, computeValidOpts, computeRowOpts, computeColumnOpts, computeRowDragOpts, computeColumnDragOpts } = $xeTable.getComputeMaps() + const { computeEditOpts, computeMouseOpts, computeAreaOpts, computeSYOpts, computeEmptyOpts, computeTooltipOpts, computeRadioOpts, computeExpandOpts, computeTreeOpts, computeCheckboxOpts, computeCellOpts, computeValidOpts, computeRowOpts, computeColumnOpts, computeRowDragOpts, computeColumnDragOpts } = $xeTable.getComputeMaps() const refElem = ref() as Ref const refBodyTable = ref() as Ref @@ -762,40 +762,32 @@ export default defineComponent({ }) const renderVN = () => { - let { fixedColumn, fixedType, tableColumn } = props - const { keyboardConfig, showOverflow: allColumnOverflow, spanMethod, mouseConfig } = tableProps - const { tableData, mergeList, scrollYLoad, isAllOverflow, isDragRowMove } = tableReactData + const { fixedColumn, fixedType, tableColumn } = props + const { showOverflow: allColumnOverflow, spanMethod, footerSpanMethod, mouseConfig } = tableProps + const { tableData, scrollXLoad, scrollYLoad, isAllOverflow, isDragRowMove, expandColumn } = tableReactData const { visibleColumn } = tableInternalData const { slots } = tableContext const rowOpts = computeRowOpts.value const sYOpts = computeSYOpts.value const emptyOpts = computeEmptyOpts.value - const keyboardOpts = computeKeyboardOpts.value const mouseOpts = computeMouseOpts.value const rowDragOpts = computeRowDragOpts.value - // const isMergeLeftFixedExceeded = computeIsMergeLeftFixedExceeded.value - // const isMergeRightFixedExceeded = computeIsMergeRightFixedExceeded.value - // 如果是使用优化模式 + + let renderColumnList = tableColumn + if (fixedType) { - // 如果存在展开行使用全量渲染 - if (!tableReactData.expandColumn && (scrollYLoad || (allColumnOverflow ? isAllOverflow : allColumnOverflow))) { - if (!mergeList.length && !spanMethod && !(keyboardConfig && keyboardOpts.isMerge)) { - tableColumn = fixedColumn + renderColumnList = visibleColumn + // 如果是使用优化模式 + if (scrollXLoad || scrollYLoad || (allColumnOverflow && isAllOverflow)) { + // 如果不支持优化模式 + if (expandColumn || spanMethod || footerSpanMethod) { + renderColumnList = visibleColumn } else { - tableColumn = visibleColumn - // 检查固定列是否被合并,合并范围是否超出固定列 - // if (mergeList.length && !isMergeLeftFixedExceeded && fixedType === 'left') { - // tableColumn = fixedColumn - // } else if (mergeList.length && !isMergeRightFixedExceeded && fixedType === 'right') { - // tableColumn = fixedColumn - // } else { - // tableColumn = visibleColumn - // } + renderColumnList = fixedColumn || [] } - } else { - tableColumn = visibleColumn } } + let emptyContent: string | VxeComponentSlotType | VxeComponentSlotType[] const emptySlot = slots ? slots.empty : null if (emptySlot) { @@ -824,7 +816,7 @@ export default defineComponent({ ...ons }, [ fixedType - ? createCommentVNode() + ? renderEmptyElement($xeTable) : h('div', { ref: refBodyXSpace, class: 'vxe-body--x-space' @@ -846,7 +838,7 @@ export default defineComponent({ */ h('colgroup', { ref: refBodyColgroup - }, (tableColumn as any[]).map((column, $columnIndex) => { + }, (renderColumnList as any[]).map((column, $columnIndex) => { return h('col', { name: column.id, key: $columnIndex @@ -861,11 +853,11 @@ export default defineComponent({ name: `vxe-body--row-list${isDragRowMove ? '' : '-disabled'}`, tag: 'tbody' }, { - default: () => renderRows(fixedType, tableData, tableColumn) + default: () => renderRows(fixedType, tableData, renderColumnList) }) : h('tbody', { ref: refBodyTBody - }, renderRows(fixedType, tableData, tableColumn)) + }, renderRows(fixedType, tableData, renderColumnList)) ]), h('div', { class: 'vxe-table--checkbox-range' diff --git a/packages/table/src/footer.ts b/packages/table/src/footer.ts index f2a3dac5a6..a004bd99f9 100644 --- a/packages/table/src/footer.ts +++ b/packages/table/src/footer.ts @@ -1,11 +1,11 @@ -import { createCommentVNode, defineComponent, TransitionGroup, h, ref, Ref, PropType, inject, nextTick, onMounted, onUnmounted } from 'vue' +import { defineComponent, TransitionGroup, h, ref, Ref, PropType, inject, nextTick, onMounted, onUnmounted } from 'vue' import XEUtils from 'xe-utils' import { VxeUI } from '../../ui' import { updateCellTitle, getPropClass, setScrollLeft } from '../../ui/src/dom' import type { VxeTablePrivateMethods, VxeTableConstructor, VxeTableMethods, VxeColumnPropTypes, VxeTableDefines } from '../../../types' -const { renderer } = VxeUI +const { renderer, renderEmptyElement } = VxeUI const renderType = 'footer' @@ -228,8 +228,8 @@ export default defineComponent({ : []) } - const renderHeads = (footerTableData: any[]) => { - const { fixedType, tableColumn } = props + const renderHeads = (renderColumnList: VxeTableDefines.ColumnInfo[]) => { + const { fixedType, footerTableData } = props const { footerRowClassName, footerRowStyle } = tableProps const { isDragColMove } = tableReactData const columnOpts = computeColumnOpts.value @@ -250,7 +250,7 @@ export default defineComponent({ ], style: footerRowStyle ? (XEUtils.isFunction(footerRowStyle) ? footerRowStyle(rowParams) : footerRowStyle) : null }, { - default: () => renderRows(tableColumn, footerTableData, row, $rowIndex, _rowIndex) + default: () => renderRows(renderColumnList, footerTableData, row, $rowIndex, _rowIndex) }) } return h('tr', { @@ -260,27 +260,28 @@ export default defineComponent({ footerRowClassName ? XEUtils.isFunction(footerRowClassName) ? footerRowClassName(rowParams) : footerRowClassName : '' ], style: footerRowStyle ? (XEUtils.isFunction(footerRowStyle) ? footerRowStyle(rowParams) : footerRowStyle) : null - }, renderRows(tableColumn, footerTableData, row, $rowIndex, _rowIndex)) + }, renderRows(renderColumnList, footerTableData, row, $rowIndex, _rowIndex)) }) } const renderVN = () => { - let { fixedType, fixedColumn, tableColumn, footerTableData } = props - const { footerSpanMethod, showFooterOverflow: allColumnFooterOverflow } = tableProps + const { fixedType, fixedColumn, tableColumn } = props + const { spanMethod, footerSpanMethod, showFooterOverflow: allColumnFooterOverflow } = tableProps const { visibleColumn } = tableInternalData - const { scrollXLoad, scrollbarWidth, mergeFooterList } = tableReactData + const { scrollbarWidth } = tableReactData + + let renderColumnList = tableColumn - // 如果是使用优化模式 if (fixedType) { - // 如果存在展开行使用全量渲染 - if (!tableReactData.expandColumn && (scrollXLoad || allColumnFooterOverflow)) { - if (!mergeFooterList.length || !footerSpanMethod) { - tableColumn = fixedColumn + renderColumnList = visibleColumn + // 如果是使用优化模式 + if (allColumnFooterOverflow) { + // 如果不支持优化模式 + if (spanMethod || footerSpanMethod) { + renderColumnList = visibleColumn } else { - tableColumn = visibleColumn + renderColumnList = fixedColumn || [] } - } else { - tableColumn = visibleColumn } } @@ -296,7 +297,7 @@ export default defineComponent({ ...ons }, [ fixedType - ? createCommentVNode() + ? renderEmptyElement($xeTable) : h('div', { ref: refFooterXSpace, class: 'vxe-body--x-space' @@ -314,7 +315,7 @@ export default defineComponent({ */ h('colgroup', { ref: refFooterColgroup - }, tableColumn.map((column, $columnIndex) => { + }, renderColumnList.map((column, $columnIndex) => { return h('col', { name: column.id, key: $columnIndex @@ -331,7 +332,7 @@ export default defineComponent({ */ h('tfoot', { ref: refFooterTFoot - }, renderHeads(footerTableData)) + }, renderHeads(renderColumnList)) ]) ]) } diff --git a/packages/table/src/header.ts b/packages/table/src/header.ts index 6ac601ea00..a353f2b2ce 100644 --- a/packages/table/src/header.ts +++ b/packages/table/src/header.ts @@ -1,4 +1,4 @@ -import { createCommentVNode, defineComponent, TransitionGroup, h, ref, Ref, PropType, inject, nextTick, watch, onMounted, onUnmounted } from 'vue' +import { defineComponent, TransitionGroup, h, ref, Ref, PropType, inject, nextTick, watch, onMounted, onUnmounted } from 'vue' import XEUtils from 'xe-utils' import { VxeUI } from '../../ui' import { convertHeaderColumnToRows, getColReMinWidth } from './util' @@ -6,7 +6,7 @@ import { hasClass, getOffsetPos, addClass, removeClass } from '../../ui/src/dom' import type { VxeTablePrivateMethods, VxeTableConstructor, VxeTableMethods, VxeTableDefines, VxeColumnPropTypes } from '../../../types' -const { renderer } = VxeUI +const { renderer, renderEmptyElement } = VxeUI const renderType = 'header' @@ -311,18 +311,24 @@ export default defineComponent({ const renderVN = () => { const { fixedType, fixedColumn, tableColumn } = props - const { showHeaderOverflow: allColumnHeaderOverflow } = tableProps - const { isGroup, scrollXLoad, scrollbarWidth } = tableReactData + const { showHeaderOverflow: allColumnHeaderOverflow, spanMethod, footerSpanMethod } = tableProps + const { isGroup, scrollbarWidth } = tableReactData const { visibleColumn } = tableInternalData let headerGroups: VxeTableDefines.ColumnInfo[][] = headerColumn.value let renderColumnList = tableColumn as VxeTableDefines.ColumnInfo[] if (isGroup) { renderColumnList = visibleColumn } else { - // 如果是使用优化模式 if (fixedType) { - if (scrollXLoad || allColumnHeaderOverflow) { - renderColumnList = fixedColumn as VxeTableDefines.ColumnInfo[] + renderColumnList = visibleColumn + // 如果是使用优化模式 + if (allColumnHeaderOverflow) { + // 如果不支持优化模式 + if (spanMethod || footerSpanMethod) { + renderColumnList = visibleColumn + } else { + renderColumnList = fixedColumn || [] + } } } headerGroups = [renderColumnList] @@ -333,7 +339,7 @@ export default defineComponent({ xid: xID }, [ fixedType - ? createCommentVNode() + ? renderEmptyElement($xeTable) : h('div', { ref: refHeaderXSpace, class: 'vxe-body--x-space' diff --git a/packages/table/src/table.ts b/packages/table/src/table.ts index f49c671282..301ed4801a 100644 --- a/packages/table/src/table.ts +++ b/packages/table/src/table.ts @@ -1730,14 +1730,13 @@ export default defineComponent({ } const updateStyle = () => { - const { border, showFooter, showOverflow: allColumnOverflow, showHeaderOverflow: allColumnHeaderOverflow, showFooterOverflow: allColumnFooterOverflow, mouseConfig, spanMethod, footerSpanMethod, keyboardConfig } = props - const { isGroup, currentRow, tableColumn, scrollXLoad, scrollYLoad, overflowX, scrollbarWidth, scrollbarHeight, columnStore, editStore, mergeList, mergeFooterList, isAllOverflow } = reactData + const { border, showFooter, showOverflow: allColumnOverflow, showHeaderOverflow: allColumnHeaderOverflow, showFooterOverflow: allColumnFooterOverflow, mouseConfig, spanMethod, footerSpanMethod } = props + const { isGroup, currentRow, tableColumn, scrollXLoad, scrollYLoad, overflowX, scrollbarWidth, scrollbarHeight, columnStore, editStore, isAllOverflow, expandColumn } = reactData let { visibleColumn, fullColumnIdData, tableHeight, tableWidth, headerHeight, footerHeight, elemStore, customHeight, customMinHeight, customMaxHeight } = internalData const containerList = ['main', 'left', 'right'] const emptyPlaceholderElem = refEmptyPlaceholder.value const cellOffsetWidth = computeCellOffsetWidth.value const mouseOpts = computeMouseOpts.value - const keyboardOpts = computeKeyboardOpts.value const bodyWrapperElem = getRefElem(elemStore['main-body-wrapper']) if (emptyPlaceholderElem) { emptyPlaceholderElem.style.top = `${headerHeight}px` @@ -1797,10 +1796,16 @@ export default defineComponent({ if (isGroup) { renderColumnList = visibleColumn } else { - // 如果是使用优化模式 if (fixedType) { - if (scrollXLoad || allColumnHeaderOverflow) { - renderColumnList = fixedColumn + renderColumnList = visibleColumn + // 如果是使用优化模式 + if (allColumnHeaderOverflow) { + // 如果不支持优化模式 + if (spanMethod || footerSpanMethod) { + renderColumnList = visibleColumn + } else { + renderColumnList = fixedColumn || [] + } } } } @@ -1884,19 +1889,19 @@ export default defineComponent({ let tWidth = tableWidth let renderColumnList = tableColumn - // 如果是使用优化模式 if (fixedType) { - // 如果存在展开行使用全量渲染 - if (!reactData.expandColumn && (scrollYLoad || (allColumnOverflow ? isAllOverflow : allColumnOverflow))) { - if (!mergeList.length && !spanMethod && !(keyboardConfig && keyboardOpts.isMerge)) { - renderColumnList = fixedColumn - } else { + renderColumnList = visibleColumn + // 如果是使用优化模式 + if (scrollXLoad || scrollYLoad || (allColumnOverflow && isAllOverflow)) { + // 如果不支持优化模式 + if (expandColumn || spanMethod || footerSpanMethod) { renderColumnList = visibleColumn + } else { + renderColumnList = fixedColumn || [] } - } else { - renderColumnList = visibleColumn } } + tWidth = renderColumnList.reduce((previous, column) => previous + column.renderWidth, 0) if (tableElem) { @@ -1911,19 +1916,20 @@ export default defineComponent({ let tWidth = tableWidth let renderColumnList = tableColumn - // 如果是使用优化模式 + if (fixedType) { - // 如果存在展开行使用全量渲染 - if (!reactData.expandColumn && (scrollXLoad || allColumnFooterOverflow)) { - if (!mergeFooterList.length || !footerSpanMethod) { - renderColumnList = fixedColumn - } else { + renderColumnList = visibleColumn + // 如果是使用优化模式 + if (allColumnFooterOverflow) { + // 如果不支持优化模式 + if (spanMethod || footerSpanMethod) { renderColumnList = visibleColumn + } else { + renderColumnList = fixedColumn || [] } - } else { - renderColumnList = visibleColumn } } + tWidth = renderColumnList.reduce((previous, column) => previous + column.renderWidth, 0) if (isNodeElement(wrapperElem)) {