import { DragDirection, EditingData, IndexColumn, RowData } from '@/lib/types'; import { GroupSelection } from '@/lib/types/group'; import { times, isFunction } from 'lodash'; import papaparse from 'papaparse'; import { getIsIncrementalArray, transpose2DArray } from '@/lib/utils/math'; import { getInnerTextByVNodesOrVNode } from '@/lib/utils/vues'; const collectRowData = ( areaSelection: GroupSelection, index2ColumnId: string[], rowData: Record, ) => { const currentRow = []; if (areaSelection.hit) { const [beginColumnIndex, endColumnIndex] = areaSelection.column; for (let i = beginColumnIndex; i <= endColumnIndex; i++) { currentRow.push(rowData[index2ColumnId[i]].value); } } return currentRow; }; const collectColumnTitle = ( areaSelection: GroupSelection, index2ColumnId: string[], columnRecord: Record, ) => { const currentRow = []; if (areaSelection.hit) { const [beginColumnIndex, endColumnIndex] = areaSelection.column; for (let i = beginColumnIndex; i <= endColumnIndex; i++) { const title = columnRecord[index2ColumnId[i]].title; if (isFunction(title)) { currentRow.push(getInnerTextByVNodesOrVNode(title())); } else { currentRow.push(title); } } } return currentRow; }; export const singleAreaData2RowColumnArray = (area: GroupSelection) => (index2RowId: string[], index2Column: string[], data2d: Record) => { // 收集数据 const rowColumn = []; const beginRowIndex = area.hit ? area.row[0] : 0; const endRowIndex = area.hit ? area.row[1] : 0; for (let i = beginRowIndex; i <= endRowIndex; i++) { const currentRow = []; const rowFieldData = data2d[index2RowId[i]]?.fieldData; if (area.hit) { currentRow.push(...collectRowData(area, index2Column, rowFieldData)); } rowColumn.push(currentRow); } return rowColumn; }; export const areaData2RowColumnArray = ( columnRecord: Record | null, leftArea: GroupSelection, scrollArea: GroupSelection, rightArea: GroupSelection, ) => ( index2RowId: string[], leftIndex2Column: string[], scrollIndex2Column: string[], rightIndex2Column: string[], data2d: Record, ) => { // 收集数据 const rowColumn = []; let beginRowIndex = 0; let endRowIndex = 0; if (leftArea.hit) { beginRowIndex = leftArea.row[0]; endRowIndex = leftArea.row[1]; } if (scrollArea.hit) { beginRowIndex = scrollArea.row[0]; endRowIndex = scrollArea.row[1]; } if (rightArea.hit) { beginRowIndex = rightArea.row[0]; endRowIndex = rightArea.row[1]; } if (columnRecord) { rowColumn.push([ ...collectColumnTitle(leftArea, leftIndex2Column, columnRecord), ...collectColumnTitle(scrollArea, scrollIndex2Column, columnRecord), ...collectColumnTitle(rightArea, rightIndex2Column, columnRecord), ]); } for (let i = beginRowIndex; i <= endRowIndex; i++) { const currentRow = []; const rowFieldData = data2d[index2RowId[i]]?.fieldData; if (leftArea.hit) { currentRow.push(...collectRowData(leftArea, leftIndex2Column, rowFieldData)); } if (scrollArea.hit) { currentRow.push(...collectRowData(scrollArea, scrollIndex2Column, rowFieldData)); } if (rightArea.hit) { currentRow.push(...collectRowData(rightArea, rightIndex2Column, rowFieldData)); } rowColumn.push(currentRow); } return rowColumn; }; export const twoDArray2CSV = (twoDArray: (string | number | boolean)[][]) => { return papaparse.unparse(twoDArray); }; export const getRowOrColumnFillingDataPath = ( columnRecord: Record, index2RowId: string[], index2ColumnId: string[], groupCalculating: GroupSelection, ): { path: string; isEditCell: boolean }[][] => { const dataPaths: { path: string; isEditCell: boolean }[][] = []; for (let rowCount = groupCalculating.row[0]; rowCount <= groupCalculating.row[1]; rowCount++) { const currentRowId = index2RowId[rowCount]; const rowPathArray = [] as { path: string; isEditCell: boolean }[]; for ( let columnCount = groupCalculating.column[0]; columnCount <= groupCalculating.column[1]; columnCount++ ) { const currentColumnId = index2ColumnId[columnCount]; rowPathArray.push({ path: `${currentRowId}.${currentColumnId}`, isEditCell: !!columnRecord[currentColumnId].editor, }); } dataPaths.push(rowPathArray); } return dataPaths; }; const calculateNextValues = (series: (string | number | boolean)[], count: number) => { // 数据只有一个-复制 if (series.length === 1) return times(count).map(() => series[0]); // 数据全相同-复制 if (series.every((itm) => itm === series[0])) return times(count).map(() => series[0]); // 数组都是数字存在递增关系-递增 const incremental = getIsIncrementalArray(series); if (incremental !== false) { let cumulative = Number(series[series.length - 1]); return times(count).map(() => { cumulative = cumulative + (incremental as number); return cumulative; }); } // 其他的-按照索引复制 let seriesCount = -1; return times(count).map(() => { seriesCount++; if (seriesCount === series.length) { seriesCount = -1; } return series[seriesCount]; }); }; const collectRightDirectionDataChangeInfo = ( rowColumnData: (string | number | boolean)[][], dataPaths: { path: string; isEditCell: boolean }[][], ) => { const result: Record = {}; // 一行一行 row 计算 dataPaths.forEach((dataPaths, index) => { // 开始算一行 const rowResult = calculateNextValues(rowColumnData[index], dataPaths.length); // 逐个添加道值组 dataPaths.forEach((path, pathIndex) => { if (path.isEditCell) { result[path.path] = rowResult[pathIndex]; } }); }); return result; }; const collectLeftDirectionDataChangeInfo = ( rowColumnData: (string | number | boolean)[][], dataPaths: { path: string; isEditCell: boolean }[][], ) => { const result: Record = {}; // 一行一行 row 计算 dataPaths.forEach((dataPaths, index) => { // 开始算一行 const rowResult = calculateNextValues(rowColumnData[index].reverse(), dataPaths.length); // 逐个添加道值组 dataPaths.forEach((path, pathIndex) => { if (!path.isEditCell) return; const currentIndex = dataPaths.length - pathIndex - 1; result[path.path] = rowResult[currentIndex]; }); }); return result; }; const collectBottomDirectionDataChangeInfo = ( rowColumnData: (string | number | boolean)[][], dataPaths: { path: string; isEditCell: boolean }[][], ) => { const result: Record = {}; const transposedRowColumnData = transpose2DArray(rowColumnData); const transposedDataPaths = transpose2DArray(dataPaths); // 一行一行 row 计算 transposedDataPaths.forEach((dataPaths, index) => { // 开始算一行 const rowResult = calculateNextValues(transposedRowColumnData[index], dataPaths.length); // 逐个添加道值组 dataPaths.forEach((path, pathIndex) => { if (!path.isEditCell) return; result[path.path] = rowResult[pathIndex]; }); }); return result; }; const collectTopDirectionDataChangeInfo = ( rowColumnData: (string | number | boolean)[][], dataPaths: { path: string; isEditCell: boolean }[][], ) => { const result: Record = {}; const transposedRowColumnData = transpose2DArray(rowColumnData); const transposedDataPaths = transpose2DArray(dataPaths); // 一行一行 row 计算 transposedDataPaths.forEach((dataPaths, index) => { // 开始算一行 const rowResult = calculateNextValues( transposedRowColumnData[index].reverse(), dataPaths.length, ); // 逐个添加道值组 dataPaths.forEach((path, pathIndex) => { if (!path.isEditCell) return; const currentIndex = dataPaths.length - pathIndex - 1; result[path.path] = rowResult[currentIndex]; }); }); return result; }; export const getChangeDataInfo = ( rowColumnData: (string | number | boolean)[][], dataPaths: { path: string; isEditCell: boolean }[][], direction: DragDirection, ) => { if (direction === DragDirection.right) { return collectRightDirectionDataChangeInfo(rowColumnData, dataPaths); } if (direction === DragDirection.left) { return collectLeftDirectionDataChangeInfo(rowColumnData, dataPaths); } if (direction === DragDirection.bottom) { return collectBottomDirectionDataChangeInfo(rowColumnData, dataPaths); } return collectTopDirectionDataChangeInfo(rowColumnData, dataPaths); }; export const getCurrentRowData = ( currentRow2DData: RowData, columnId2Field: Record, ) => { const otherData = currentRow2DData.otherData; const fieldData = currentRow2DData.fieldData; const result = {}; Object.keys(otherData).forEach((key) => { if (fieldData[key]) { result[key] = fieldData[key].value; } else { result[key] = otherData[key]; } }); Object.keys(fieldData).forEach((key) => { result[columnId2Field[key]] = fieldData[key].value; }); return result; };