import { IStoreState, IRow, ID, ICell } from './index.data'; import { getCell, getRow } from './store/selectors'; import { TreeContext, renderCatalogNo } from 'valor-app-utils'; import { getRightCell as _getRightCell, getRowNoCellValueByRow, getCellij, } from './store/selectors/cell'; import { getSelectedRow } from './store/selectors/row'; import { fillij } from './store/selectors/cell'; import * as R from 'rambda'; import { IRowWithCell } from './SpreadSheetProvider/index.data'; import { makeStoreState } from './SpreadSheetProvider/helper'; import { getLabelByIj } from './store/formula_support'; import { rowNoTemplates } from './constants'; export { getFormattedValue } from './cellTypes/numeric/NumericRenderer'; export { getValue } from './utils'; export { getCellij } from './store/selectors/cell'; export { getColumnWithCellsByIndex, getColumn } from './store/selectors/column'; /**** 这里包含了所有对客户组件提供的helper方法 *****/ /** * 如果有选择行或单元格, 并且是单选, 则找出其level=1的行 ( 顶级行 ) * A * A1 * A2 * 则getTopRow(A2) => A */ export function getTopRow(state: IStoreState): IRow | null { const { selectionType, selectedCellRange, selectedRowRange, treeContext } = state; let rowId: ID; if (selectionType === 'row') { if (selectedRowRange[0] !== selectedRowRange[1]) { return null; } rowId = selectedRowRange[0]; } else if (selectionType === 'cell') { const cell0 = getCell(state, selectedCellRange[0])!; const cell1 = getCell(state, selectedCellRange[1])!; if (getCellij(state, cell0.id).i !== getCellij(state, cell1.id).i) return null; rowId = cell0.rowId!; } else { return null; } // 只有tree area才有top row const row = getRow(state, rowId); if (!row || row.type !== 'body' || (row.area || 'tree') !== 'tree') return null; function getTopRowId(rowId: ID, treeContext: TreeContext): ID { if (treeContext[rowId].level === 1) return rowId; return getTopRowId(treeContext[rowId].parentId, treeContext); } const topRowId = getTopRowId(rowId, treeContext); return getRow(state, topRowId); } export const getRightCell = _getRightCell; export function getRowNoValue(state: IStoreState, rowId: ID, templates?: string[]) { templates = templates || rowNoTemplates; const { path } = getRowNoCellValueByRow(state, rowId); return renderCatalogNo(templates[path.length - 1], path.map(i => i + 1)); } // 获取当前选择行 export { getSelectedRow }; // 获取对外输出的state, 目前主要用于填充ij export function getNormalizedState(state: IStoreState, rowNoTemplates?: string[]): IStoreState { const withIj = fillij(state); const cellsWithRowNo = R.map((cell, cellId) => { if (cell.type === 'row-no') { const row = getRow(state, cell.rowId!); if (row.type === 'body' && (row.area || 'tree') === 'tree') { const rowNo = getRowNoValue(state, row.id, rowNoTemplates); return Object.assign({}, cell, { value: rowNo }); } } return cell; }, withIj.cells); return Object.assign({}, withIj, { cells: cellsWithRowNo }); } /** * @param state * @param withNullPlacement 如果合并单元格造成的空单元格, 是否使用占位单元格? * 例: cells:[{id:1,colspan:2}] => 可能扩展出 cells:[{id:1,colspan:2}, null] */ export function getRowsWithCells(state: IStoreState, withNullPlacement = false): IRowWithCell[] { const getCellIds = (cellIds: (ID | null)[]) => { return withNullPlacement ? cellIds : cellIds.filter(Boolean); }; return state.rows.map(row => ({ ...row, cells: row.cellIds ? getCellIds(row.cellIds).map(id => state.cells[id + '']) : [], })); } export { makeStoreState }; export const getRowById = getRow; export const getCellById = getCell; // 在state.cells的每个单独的cell上, 添加 {label:'A1'} // 需要保证cell.i/cell.j存在并正确 ( 从数据库出来的数据, ij一定正确 ) export function attachCellLabel(state: IStoreState) { const cells = R.map( (cell, cellId) => ({ ...cell, label: getLabelByIj(cell.i!, cell.j!) }), state.cells, ); return { ...state, cells }; } /** * 初始化时, 填充row的i, 填充cell.ij * 底层未提供此方法 * @param cells */ export function fillRowiAndCellij(rows: IRowWithCell[]): IRowWithCell[] { return rows.map((row, i) => { const cells = (row.cells || ([] as ICell[])).map((cell, j) => cell ? Object.assign(cell, { i, j, rowId: row.id }) : null, ); return Object.assign(row, { i, cells }); }); }