/** * 草稿态分页管理模块 * * 职责: * 1. 草稿池管理:insertRows / updateRows / deleteRows * 2. 分页管理:远程数据与本地数据混排 * 3. 选中状态管理:跨页勾选状态同步 * 4. 行状态恢复:_rowState 字段维护 * * 使用方式: * var draftManager = window.DraftPageManager.createDraftManager({ * keyField: 'subid', * pageSize: 50 * }); */ (function(window) { 'use strict'; /** * 创建草稿态管理器实例 * @param {Object} config 配置参数 * @param {string} config.keyField 主键字段名,默认 'id' * @param {number} config.pageSize 每页条数,默认 50 * @returns {Object} 管理器实例 */ function createDraftManager(config) { var keyField = config && config.keyField || 'id'; var defaultPageSize = config && config.pageSize || 50; var state = { pagination: { pageSize: defaultPageSize, pageNumber: 1, total: 0, remoteTotal: 0 }, currentRemoteRows: [], insertRows: [], updateRows: [], deleteRows: [], selectedRows: [], isAllChecked: false, excludedRows: [] }; // ==================== 状态查询方法 ==================== function getPagination() { return { pageNumber: state.pagination.pageNumber, pageSize: state.pagination.pageSize, total: state.pagination.total, remoteTotal: state.pagination.remoteTotal }; } function getInsertRows() { return state.insertRows; } function getUpdateRows() { return state.updateRows; } function getDeleteRows() { return state.deleteRows; } function getSelectedRows() { return state.selectedRows; } function getValidSelectedRows() { return state.selectedRows.filter(function(row) { return row._rowState !== 'delete'; }); } function getDeletedSelectedRows() { return state.selectedRows.filter(function(row) { return row._rowState === 'delete'; }); } function isAllChecked() { return state.isAllChecked; } function getExcludedRows() { return state.excludedRows; } // ==================== 草稿池操作方法 ==================== function addInsertRow(row) { if (!row._rowState) { row._rowState = 'insert'; } var key = getRowKey(row); var exists = state.insertRows.some(function(r) { return getRowKey(r) === key; }); if (!exists) { state.insertRows.push(row); } } function removeInsertRow(row) { var key = getRowKey(row); state.insertRows = state.insertRows.filter(function(r) { return getRowKey(r) !== key; }); } function addToUpdateRows(row) { var key = getRowKey(row); var exists = state.updateRows.some(function(r) { return getRowKey(r) === key; }); if (!exists) { state.updateRows.push(row); } } function removeFromUpdateRows(row) { var key = getRowKey(row); state.updateRows = state.updateRows.filter(function(r) { return getRowKey(r) !== key; }); } function addToDeleteRows(row) { var key = getRowKey(row); var exists = state.deleteRows.some(function(r) { return getRowKey(r) === key; }); if (!exists) { state.deleteRows.push(row); } } function removeFromDeleteRows(row) { var key = getRowKey(row); state.deleteRows = state.deleteRows.filter(function(r) { return getRowKey(r) !== key; }); } // ==================== 选中状态操作方法 ==================== function addSelectedRow(row) { var key = getRowKey(row); for (var i = 0; i < state.selectedRows.length; i++) { if (getRowKey(state.selectedRows[i]) === key) { state.selectedRows[i] = row; return; } } state.selectedRows.push(row); } function removeSelectedRow(row) { var key = getRowKey(row); state.selectedRows = state.selectedRows.filter(function(item) { return getRowKey(item) !== key; }); } function clearSelectedRows() { state.selectedRows = []; } function setAllChecked(value) { state.isAllChecked = value; if (value) { clearSelectedRows(); } } function addExcludedRow(row) { if (isRowExcluded(row)) { return; } state.excludedRows.push(row); } function removeExcludedRow(row) { var key = getRowKey(row); state.excludedRows = state.excludedRows.filter(function(r) { return getRowKey(r) !== key; }); } function clearExcludedRows() { state.excludedRows = []; } function isRowExcluded(row) { var key = getRowKey(row); return state.excludedRows.some(function(r) { return getRowKey(r) === key; }); } // ==================== 分页操作方法 ==================== function setPageNumber(pageNumber) { state.pagination.pageNumber = pageNumber; } function setPageSize(pageSize) { state.pagination.pageSize = pageSize; } function setRemoteTotal(remoteTotal) { state.pagination.remoteTotal = remoteTotal; state.pagination.total = getActualTotal(); } function setCurrentRemoteRows(rows) { state.currentRemoteRows = rows; } function buildPageData(remoteRows, pageNumber) { var pageSize = state.pagination.pageSize; var remoteTotal = state.pagination.remoteTotal; var insertRows = state.insertRows; var pageStart = (pageNumber - 1) * pageSize; var pageEnd = pageStart + pageSize; remoteRows.forEach(function(row) { if (!row._rowState) { row._rowState = ''; } }); insertRows.forEach(function(row) { if (!row._rowState) { row._rowState = 'insert'; } }); var result = []; result = result.concat(remoteRows); var insertStartIdx = Math.max(0, pageStart - remoteTotal); var insertEndIdx = pageEnd - remoteTotal; if (insertStartIdx < insertRows.length) { var insertSlice = insertRows.slice(insertStartIdx, insertEndIdx); result = result.concat(insertSlice); } if (result.length > pageSize) { result = result.slice(0, pageSize); } return result; } function restoreRowStates(rows) { rows.forEach(function(row) { var key = getRowKey(row); var deleteMatch = state.deleteRows.find(function(r) { return getRowKey(r) === key; }); if (deleteMatch) { row._rowState = 'delete'; if (deleteMatch._undoRowState !== undefined) { row._undoRowState = deleteMatch._undoRowState; } return; } var insertMatch = state.insertRows.find(function(r) { return getRowKey(r) === key; }); if (insertMatch) { row._rowState = insertMatch._rowState || 'insert'; return; } var updateMatch = state.updateRows.find(function(r) { return getRowKey(r) === key; }); if (updateMatch) { row._rowState = 'update'; return; } row._rowState = ''; }); } // ==================== 工具方法 ==================== function getRowKey(row) { return row[keyField]; } function isInsertRow(row) { return row._rowState === 'insert'; } function isDeleteRow(row) { return row._rowState === 'delete'; } function isUpdateRow(row) { return row._rowState === 'update'; } function isInInsertRows(row) { var key = getRowKey(row); return state.insertRows.some(function(r) { return getRowKey(r) === key; }); } function isSavedRow(row) { return !isInsertRow(row) && !isInInsertRows(row); } function getActualTotal() { return state.pagination.remoteTotal + state.insertRows.length; } function getDisplayTotal() { var insertDisplayCount = state.insertRows.filter(function(row) { return row._rowState !== 'delete'; }).length; return state.pagination.remoteTotal + insertDisplayCount; } function getTotalPages() { return Math.ceil(getActualTotal() / state.pagination.pageSize); } function hasInsertRowsInPage(pageNumber) { var range = getPageRange(pageNumber); var remoteTotal = state.pagination.remoteTotal; return range.start < remoteTotal + state.insertRows.length && range.end > remoteTotal; } function isInsertOnlyPage(pageNumber) { var range = getPageRange(pageNumber); return range.start >= state.pagination.remoteTotal; } function getPageRange(pageNumber) { var pageSize = state.pagination.pageSize; var startIdx = (pageNumber - 1) * pageSize; var endIdx = startIdx + pageSize; return { start: startIdx, end: endIdx }; } function removeSelectionForRows(gridRows) { var drop = {}; for (var i = 0; i < gridRows.length; i++) { drop[getRowKey(gridRows[i])] = true; } state.selectedRows = state.selectedRows.filter(function(item) { return !drop[getRowKey(item)]; }); } function reset() { state.pagination = { pageSize: defaultPageSize, pageNumber: 1, total: 0, remoteTotal: 0 }; state.currentRemoteRows = []; state.insertRows = []; state.updateRows = []; state.deleteRows = []; state.selectedRows = []; state.isAllChecked = false; state.excludedRows = []; } return { getPagination: getPagination, getInsertRows: getInsertRows, getUpdateRows: getUpdateRows, getDeleteRows: getDeleteRows, getSelectedRows: getSelectedRows, getValidSelectedRows: getValidSelectedRows, getDeletedSelectedRows: getDeletedSelectedRows, isAllChecked: isAllChecked, getExcludedRows: getExcludedRows, addInsertRow: addInsertRow, removeInsertRow: removeInsertRow, addToUpdateRows: addToUpdateRows, removeFromUpdateRows: removeFromUpdateRows, addToDeleteRows: addToDeleteRows, removeFromDeleteRows: removeFromDeleteRows, addSelectedRow: addSelectedRow, removeSelectedRow: removeSelectedRow, clearSelectedRows: clearSelectedRows, setAllChecked: setAllChecked, addExcludedRow: addExcludedRow, removeExcludedRow: removeExcludedRow, clearExcludedRows: clearExcludedRows, isRowExcluded: isRowExcluded, setPageNumber: setPageNumber, setPageSize: setPageSize, setRemoteTotal: setRemoteTotal, setCurrentRemoteRows: setCurrentRemoteRows, buildPageData: buildPageData, restoreRowStates: restoreRowStates, getRowKey: getRowKey, isInsertRow: isInsertRow, isDeleteRow: isDeleteRow, isUpdateRow: isUpdateRow, isInInsertRows: isInInsertRows, isSavedRow: isSavedRow, getActualTotal: getActualTotal, getDisplayTotal: getDisplayTotal, getTotalPages: getTotalPages, hasInsertRowsInPage: hasInsertRowsInPage, isInsertOnlyPage: isInsertOnlyPage, removeSelectionForRows: removeSelectionForRows, reset: reset }; } window.DraftPageManager = { createDraftManager: createDraftManager }; })(window);