diff --git a/.husky/prepare-commit-msg b/.husky/prepare-commit-msg index 71fe5b35a..672056774 100755 --- a/.husky/prepare-commit-msg +++ b/.husky/prepare-commit-msg @@ -1,4 +1,6 @@ #!/bin/sh +[[ "$(uname -a)" = *"MINGW64"* ]] && exit 0 +[ -n "$CI" ] && exit 0 . "$(dirname "$0")/_/husky.sh" exec < /dev/tty && npx git-cz --hook || true \ No newline at end of file diff --git a/src/_util/callBoth.ts b/src/_util/callBoth.ts index b47df5661..57e0bac7a 100644 --- a/src/_util/callBoth.ts +++ b/src/_util/callBoth.ts @@ -9,7 +9,6 @@ export default function callBoth any>(...fns: T[]) lastResult = fn(...args); } } - return lastResult; }) as T; } diff --git a/src/_util/dom.ts b/src/_util/dom.ts index bd5733088..bdd699661 100644 --- a/src/_util/dom.ts +++ b/src/_util/dom.ts @@ -38,7 +38,7 @@ export const off = ((): any => { }; })(); -function hasClass(el: Element, cls: string) { +export function hasClass(el: Element, cls: string) { if (!el || !cls) return false; if (cls.indexOf(' ') !== -1) throw new Error('className should not contain space.'); if (el.classList) { diff --git a/src/table/BaseTable.tsx b/src/table/BaseTable.tsx index b6b4f0c79..35373f80a 100644 --- a/src/table/BaseTable.tsx +++ b/src/table/BaseTable.tsx @@ -157,7 +157,7 @@ const BaseTable = forwardRef((props: TBaseTableProps, ref) => { const getTFootHeight = () => { if (!tableElmRef.current) return; const timer = setTimeout(() => { - const height = tableElmRef.current.querySelector('tfoot')?.getBoundingClientRect().height; + const height = tableElmRef.current?.querySelector('tfoot')?.getBoundingClientRect().height; setTableFootHeight(height); clearTimeout(timer); }); diff --git a/src/table/PrimaryTable.tsx b/src/table/PrimaryTable.tsx index d55bf2557..bd6ea230e 100644 --- a/src/table/PrimaryTable.tsx +++ b/src/table/PrimaryTable.tsx @@ -66,10 +66,8 @@ export default function PrimaryTable(props: TPrimaryTableProps) { if (isRowHandlerDraggable || isRowDraggable) { tAttributes.push(({ row }) => ({ 'data-id': get(row, props.rowKey || 'id') })); } - console.log(tAttributes); return tAttributes.filter((v) => v); })(); - // 1. 影响列数量的因素有:自定义列配置、展开/收起行、多级表头;2. 影响表头内容的因素有:排序图标、筛选图标 const getColumns = (columns: PrimaryTableCol[]) => { const arr: PrimaryTableCol[] = []; diff --git a/src/table/TBody.tsx b/src/table/TBody.tsx index a644c1c2f..ca36486d4 100644 --- a/src/table/TBody.tsx +++ b/src/table/TBody.tsx @@ -57,12 +57,13 @@ export const extendTableProps = [ export default function TBody(props: TableBodyProps) { // 如果不是变量复用,没必要对每一个参数进行解构(解构过程需要单独的内存空间存储临时变量) - const { data, columns, rowKey } = props; + const { data, columns, rowKey, firstFullRow, lastFullRow } = props; const [global, t] = useLocaleReceiver('table'); const { tableFullRowClasses, tableBaseClass } = useClassName(); const { skipSpansMap } = useRowspanAndColspan(data, columns, rowKey, props.rowspanAndColspan); const tbodyClasses = useMemo(() => [tableBaseClass.body], [tableBaseClass.body]); + const hasFullRowConfig = useMemo(() => firstFullRow || lastFullRow, [firstFullRow, lastFullRow]); const renderEmpty = (columns: TableBodyProps['columns']) => ( @@ -80,9 +81,10 @@ export default function TBody(props: TableBodyProps) { const getFullRow = (columnLength: number, type: 'first-full-row' | 'last-full-row') => { const tType = camelCase(type); const fullRowNode = { - 'first-full-row': props.firstFullRow, - 'last-full-row': props.lastFullRow, + 'first-full-row': firstFullRow, + 'last-full-row': lastFullRow, }[type]; + if (!fullRowNode) return null; const isFixedToLeft = props.isWidthOverflow && columns.find((col) => col.fixed === 'left'); const classes = [tableFullRowClasses.base, tableFullRowClasses[tType]]; @@ -157,7 +159,7 @@ export default function TBody(props: TableBodyProps) { {getFullRow(columnLength, 'last-full-row')} ); - const isEmpty = !data?.length && !props.loading; + const isEmpty = !data?.length && !props.loading && !hasFullRowConfig; const translate = `translate(0, ${props.translateY}px)`; const posStyle = { diff --git a/src/table/hooks/useDragSort.ts b/src/table/hooks/useDragSort.ts index c4bdfd120..a3b79e9f8 100644 --- a/src/table/hooks/useDragSort.ts +++ b/src/table/hooks/useDragSort.ts @@ -1,9 +1,10 @@ // 表格 行拖拽 + 列拖拽功能 import { MutableRefObject, useEffect, useMemo, useRef, useState } from 'react'; -import Sortable, { SortableEvent, SortableOptions } from 'sortablejs'; +import Sortable, { SortableEvent, SortableOptions, MoveEvent } from 'sortablejs'; import get from 'lodash/get'; import { TableRowData, TdPrimaryTableProps, DragSortContext, PrimaryTableCol } from '../type'; import useClassName from './useClassName'; +import { hasClass } from '../../_util/dom'; import log from '../../_common/js/log'; import swapDragArrayElement from '../../_common/js/utils/swapDragArrayElement'; import { BaseTableColumns } from '../interface'; @@ -19,7 +20,7 @@ import { BaseTableColumns } from '../interface'; */ export default function useDragSort(props: TdPrimaryTableProps, primaryTableRef: MutableRefObject) { const { sortOnRowDraggable, dragSort, data, onDragSort } = props; - const { tableDraggableClasses, tableBaseClass } = useClassName(); + const { tableDraggableClasses, tableBaseClass, tableFullRowClasses } = useClassName(); const [columns, setDragSortColumns] = useState(props.columns || []); // 判断是否有拖拽列。此处重点测试树形结构的拖拽排序 const dragCol = useMemo(() => columns.find((item) => item.colKey === 'drag'), [columns]); @@ -71,10 +72,13 @@ export default function useDragSort(props: TdPrimaryTableProps, primaryTableRef: ghostClass: tableDraggableClasses.ghost, chosenClass: tableDraggableClasses.chosen, dragClass: tableDraggableClasses.dragging, + filter: `.${tableFullRowClasses.base}`, // 过滤首行尾行固定 + onMove: (evt: MoveEvent) => !hasClass(evt.related, tableFullRowClasses.base), onEnd: (evt: SortableEvent) => { // 处理受控:拖拽列表恢复原始排序,等待外部数据 data 变化,更新最终顺序 - dragInstanceTmp?.sort([...lastRowList.current]); let { oldIndex: currentIndex, newIndex: targetIndex } = evt; + + dragInstanceTmp?.sort([...lastRowList.current]); if (props.firstFullRow) { currentIndex -= 1; targetIndex -= 1; @@ -91,7 +95,7 @@ export default function useDragSort(props: TdPrimaryTableProps, primaryTableRef: }; // currentData is going to be deprecated. params.currentData = params.newData; - console.log([...tData.current], { ...params }); + onDragSort?.(params); }, }; diff --git a/src/table/hooks/useFixed.ts b/src/table/hooks/useFixed.ts index 71be1bd06..67ff58994 100644 --- a/src/table/hooks/useFixed.ts +++ b/src/table/hooks/useFixed.ts @@ -268,6 +268,7 @@ export default function useFixed(props: TdBaseTableProps) { const updateRowAndColFixedPosition = (tableContentElm: HTMLElement, initialColumnMap: RowAndColFixedPosition) => { rowAndColFixedPosition.clear(); + if (!tableContentElm) return; const thead = tableContentElm.querySelector('thead'); // 处理固定列 thead && setFixedColPosition(thead.children, initialColumnMap); @@ -281,7 +282,7 @@ export default function useFixed(props: TdBaseTableProps) { let shadowLastScrollLeft: number; const updateColumnFixedShadow = (target: HTMLElement) => { - if (!isFixedColumn) return; + if (!isFixedColumn || !target) return; const { scrollLeft } = target; // 只有左右滚动,需要更新固定列阴影 if (shadowLastScrollLeft === scrollLeft) return; @@ -346,6 +347,7 @@ export default function useFixed(props: TdBaseTableProps) { const updateTableWidth = () => { const rect = tableContentRef.current?.getBoundingClientRect?.(); + if (!rect) return; // 存在纵向滚动条,且固定表头时,需去除滚动条宽度 const reduceWidth = isFixedHeader ? scrollbarWidth : 0; setTableWidth(rect.width - reduceWidth - (props.bordered ? 1 : 0)); @@ -370,7 +372,8 @@ export default function useFixed(props: TdBaseTableProps) { if (notNeedThWidthList) return; const timer = setTimeout(() => { updateTableWidth(); - const thead = tableContentRef.current.querySelector('thead'); + const thead = tableContentRef.current?.querySelector('thead'); + if (!thead) return; updateThWidthList(thead.children); clearTimeout(timer); }, 0);