import { ICommand } from 'valor-unistore-undo'; import * as R from 'rambda'; import { IStoreState, IRow, IColumn, ICellNN, ID, ICell } from '../index.data'; import { SpreadSheetRuntime } from '../RuntimeContext'; import { deleteColumn } from '../store/actions/column'; import { dropIndex, dissoc, idMap, insertIndex } from 'valor-app-utils'; import { recalculate } from '../store/actions/recalculate'; export interface DeleteColumnCommandParams { j: number; } interface IUndoContext { deletedColumn: IColumn; // 合并主单元格的colspan将被修改, 在撤销时直接用它替换回去 updatedStaleCells: ICellNN[]; // 被删除的单元格, 在撤销时将移回去 // 从第1行到第N行顺序排列, 一个都不能少 deletedCells: ICell[]; // 新创建的单元格, 从第1行到第N行顺序排列, 若无为null insertedCells: ICell[]; } class DeleteColumnCommand extends ICommand< IStoreState, DeleteColumnCommandParams, IUndoContext, SpreadSheetRuntime > { execute = () => { const state = this.store.getState(); if (this.params.j > state.columns.length || this.params.j < 0) throw new Error(`j的长度范围: [0, ${state.columns.length - 1}], 但当前为${this.params.j}`); const result = deleteColumn(state, this.params.j, this.runtime!); this.store.setState(Object.assign(result.newState, { readyDimensions: true }) as any); this.undoContext = { deletedColumn: R.clone(state.columns[this.params.j]), updatedStaleCells: result.updatedStaleCells, deletedCells: result.deletedCells, insertedCells: result.insertedCells, }; setTimeout(() => { this.runtime!.setSheetDimensions(); // 暂时默认选中第一个单元格, 否则会抛异常 this.runtime!.fsmService.send({ type: 'SELECT.CELL', selectedCell: result.newState.rows[0].cellIds![0]!, }); }); return true; }; undo = () => { const state = this.store.getState(); const newState = undoDeleteColumn( state, this.params.j, this.undoContext.deletedColumn, this.undoContext.deletedCells, this.undoContext.insertedCells, this.undoContext.updatedStaleCells, this.runtime!, ).newState; this.store.setState(Object.assign(newState, { readyDimensions: true }) as any); setTimeout(() => { this.runtime!.setSheetDimensions(); // 暂时默认选中第一个单元格, 否则会抛异常 this.runtime!.fsmService.send({ type: 'SELECT.CELL', selectedCell: newState.rows[0].cellIds![0]!, }); }); }; } export function undoDeleteColumn( state: IStoreState, j: number, deletedColumn: IColumn, // 被删除需要恢复的单元格, 在原第j列 deletedCells: ICell[], // 创建的新单元格, 在原第j+1列, 新j列 insertedCells: ICell[], updatedStaleCells: ICellNN[], runtime: SpreadSheetRuntime, ) { const updatedColumns = [ ...state.columns.slice(0, j), deletedColumn, ...state.columns.slice(j).map(it => ({ ...it, j: it.j! + 1 })), ]; const updatedRows = state.rows.map((row, i) => { const cellIds = insertIndex(row.cellIds!, j, deletedCells[i] ? deletedCells[i]!.id : null); if (insertedCells[i]) { // 当前行创建了新单元格, 需替换为null cellIds[j + 1] = null; } return Object.assign({}, row, { cellIds }); }); const newStateAfterUndo = { rows: updatedRows, columns: updatedColumns, cells: Object.assign( {}, dissoc(state.cells, insertedCells.filter(Boolean).map(it => it!.id + '')), idMap(deletedCells.filter(Boolean)), idMap(updatedStaleCells), ), }; const calculatedStatePatch = runtime.batchMode ? Object.assign({}, newStateAfterUndo) : recalculate( { ...state, ...newStateAfterUndo }, { force: true, config: runtime && runtime.formulaManager.config }, ); return { newState: { rows: updatedRows, columns: updatedColumns, ...calculatedStatePatch }, }; } export default DeleteColumnCommand;