1307 lines
45 KiB
JavaScript
1307 lines
45 KiB
JavaScript
/**
|
|
* DataGrid 公共管理模块 - 重构版本
|
|
*
|
|
* 核心架构:全局缓存 + 单状态源
|
|
*
|
|
* 设计原则:
|
|
* 1. 单状态源:所有状态仅保存在 row 对象上
|
|
* 2. 全局缓存层:所有数据统一进入 allRowMap
|
|
* 3. 状态标记:通过 row._draftState 标识状态
|
|
* 4. 分页安全:状态不依赖当前页数据,从缓存恢复
|
|
*
|
|
* 状态定义:
|
|
* - _isNew: true 表示前端新增未提交数据
|
|
* - _draftState: null | 'add' | 'update' | 'delete'
|
|
* - _originData: 原始数据备份(用于撤销)
|
|
* - _changedFields: 变更字段列表
|
|
*
|
|
* 使用方式:
|
|
* var gridManager = createDataGridManager({
|
|
* gridId: 'feegrid',
|
|
* keyField: 'subid',
|
|
* viewName: 'v_cwzd_orderfee_s',
|
|
* baseSearchCondition: "mx_zdorderid='xxx'",
|
|
* onLoadSuccess: function(rows) { ... },
|
|
* onAfterEdit: function(rowIndex, row, changes) { ... },
|
|
* onSelectionChange: function() { ... }
|
|
* });
|
|
*/
|
|
(function (window) {
|
|
"use strict";
|
|
|
|
// ==================== GlobalCacheManager(全局缓存管理器)====================
|
|
|
|
/**
|
|
* 创建全局缓存管理器
|
|
* @param {Object} config 配置参数
|
|
* @param {string} config.keyField 主键字段名
|
|
*/
|
|
function createGlobalCacheManager(config) {
|
|
var keyField = (config && config.keyField) || "id";
|
|
|
|
var allRowMap = {};
|
|
var draftRowMap = {};
|
|
var selectionMap = {};
|
|
var exclusionMap = {};
|
|
var isAllChecked = false;
|
|
var isBatchDeleting = false;
|
|
|
|
function cloneRow(obj) {
|
|
if (!obj) return null;
|
|
return JSON.parse(JSON.stringify(obj));
|
|
}
|
|
|
|
function getRowKey(row) {
|
|
return row[keyField];
|
|
}
|
|
|
|
function initDraftState(rowId) {
|
|
if (!draftRowMap[rowId]) {
|
|
draftRowMap[rowId] = {
|
|
state: null,
|
|
originData: null,
|
|
changedFields: []
|
|
};
|
|
}
|
|
return draftRowMap[rowId];
|
|
}
|
|
|
|
function setRowToCache(row, isNew) {
|
|
var key = getRowKey(row);
|
|
var cachedRow = cloneRow(row);
|
|
|
|
if (!allRowMap[key]) {
|
|
cachedRow._isNew = isNew || false;
|
|
cachedRow._draftState = isNew ? 'add' : null;
|
|
cachedRow._originData = isNew ? null : cloneRow(row);
|
|
cachedRow._changedFields = [];
|
|
} else {
|
|
cachedRow._isNew = allRowMap[key]._isNew;
|
|
cachedRow._draftState = allRowMap[key]._draftState;
|
|
cachedRow._originData = allRowMap[key]._originData;
|
|
cachedRow._changedFields = allRowMap[key]._changedFields;
|
|
}
|
|
|
|
allRowMap[key] = cachedRow;
|
|
return cachedRow;
|
|
}
|
|
|
|
function getRowFromCache(rowId) {
|
|
return allRowMap[rowId] || null;
|
|
}
|
|
|
|
function removeRowFromCache(rowId) {
|
|
delete allRowMap[rowId];
|
|
delete draftRowMap[rowId];
|
|
delete selectionMap[rowId];
|
|
delete exclusionMap[rowId];
|
|
}
|
|
|
|
function updateRowInCache(row) {
|
|
var key = getRowKey(row);
|
|
var existing = allRowMap[key];
|
|
|
|
if (!existing) {
|
|
return setRowToCache(row, false);
|
|
}
|
|
|
|
var draftState = existing._draftState;
|
|
|
|
if (draftState !== 'delete') {
|
|
existing._draftState = existing._isNew ? 'add' : 'update';
|
|
|
|
for (var field in row) {
|
|
if (field !== keyField && field.indexOf('_') !== 0) {
|
|
if (!existing._originData) {
|
|
existing._originData = cloneRow(existing);
|
|
}
|
|
if (existing._originData[field] !== row[field]) {
|
|
if (existing._changedFields.indexOf(field) === -1) {
|
|
existing._changedFields.push(field);
|
|
}
|
|
} else {
|
|
var idx = existing._changedFields.indexOf(field);
|
|
if (idx !== -1) {
|
|
existing._changedFields.splice(idx, 1);
|
|
}
|
|
}
|
|
existing[field] = row[field];
|
|
}
|
|
}
|
|
}
|
|
|
|
return existing;
|
|
}
|
|
|
|
function markRowDeleted(row) {
|
|
var key = getRowKey(row);
|
|
var cachedRow = allRowMap[key];
|
|
|
|
if (!cachedRow) {
|
|
cachedRow = setRowToCache(row, false);
|
|
}
|
|
|
|
if (cachedRow._isNew) {
|
|
removeRowFromCache(key);
|
|
return true;
|
|
}
|
|
|
|
if (cachedRow._draftState !== 'delete') {
|
|
if (!cachedRow._originData) {
|
|
cachedRow._originData = cloneRow(cachedRow);
|
|
}
|
|
cachedRow._draftState = 'delete';
|
|
cachedRow._changedFields = [];
|
|
}
|
|
|
|
if (!isAllChecked) {
|
|
setSelection(key, false);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
function unmarkRowDeleted(row) {
|
|
var key = getRowKey(row);
|
|
var cachedRow = allRowMap[key];
|
|
|
|
if (!cachedRow || cachedRow._draftState !== 'delete') {
|
|
return false;
|
|
}
|
|
|
|
if (cachedRow._originData) {
|
|
var originState = cachedRow._originData._draftState;
|
|
cachedRow._draftState = originState || null;
|
|
cachedRow._changedFields = cachedRow._originData._changedFields || [];
|
|
|
|
for (var field in cachedRow._originData) {
|
|
if (field.indexOf('_') !== 0) {
|
|
cachedRow[field] = cachedRow._originData[field];
|
|
}
|
|
}
|
|
} else {
|
|
cachedRow._draftState = null;
|
|
cachedRow._changedFields = [];
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
function setSelection(rowId, selected) {
|
|
selectionMap[rowId] = selected;
|
|
}
|
|
|
|
function isSelected(rowId) {
|
|
return selectionMap[rowId] === true;
|
|
}
|
|
|
|
function setExclusion(rowId, excluded) {
|
|
exclusionMap[rowId] = excluded;
|
|
}
|
|
|
|
function isExcluded(rowId) {
|
|
return exclusionMap[rowId] === true;
|
|
}
|
|
|
|
function clearAllSelections() {
|
|
selectionMap = {};
|
|
}
|
|
|
|
function clearAllExclusions() {
|
|
exclusionMap = {};
|
|
}
|
|
|
|
function applyDraftStateToRemoteRows(remoteRows) {
|
|
var result = [];
|
|
|
|
for (var i = 0; i < remoteRows.length; i++) {
|
|
var row = remoteRows[i];
|
|
var key = getRowKey(row);
|
|
var cachedRow = allRowMap[key];
|
|
|
|
if (cachedRow) {
|
|
if (isBatchDeleting && !exclusionMap[key] && cachedRow._draftState !== 'add') {
|
|
cachedRow._draftState = 'delete';
|
|
if (!cachedRow._originData) {
|
|
cachedRow._originData = cloneRow(cachedRow);
|
|
}
|
|
var deleteRow = cloneRow(cachedRow);
|
|
deleteRow._rowState = 'delete';
|
|
result.push(deleteRow);
|
|
} else if (cachedRow._draftState === 'delete') {
|
|
var deleteRow = cloneRow(cachedRow);
|
|
deleteRow._rowState = 'delete';
|
|
result.push(deleteRow);
|
|
} else if (cachedRow._draftState === 'add' || cachedRow._draftState === 'update') {
|
|
var draftRow = cloneRow(cachedRow);
|
|
draftRow._rowState = cachedRow._draftState;
|
|
result.push(draftRow);
|
|
} else {
|
|
setRowToCache(row, false);
|
|
result.push(cloneRow(row));
|
|
}
|
|
} else {
|
|
setRowToCache(row, false);
|
|
|
|
if (isBatchDeleting && !exclusionMap[key]) {
|
|
var newCachedRow = allRowMap[key];
|
|
newCachedRow._draftState = 'delete';
|
|
if (!newCachedRow._originData) {
|
|
newCachedRow._originData = cloneRow(newCachedRow);
|
|
}
|
|
var deleteRow = cloneRow(newCachedRow);
|
|
deleteRow._rowState = 'delete';
|
|
result.push(deleteRow);
|
|
} else {
|
|
result.push(cloneRow(row));
|
|
}
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
function getRowsForSubmission() {
|
|
var addRows = [];
|
|
var updateRows = [];
|
|
var deleteRows = [];
|
|
|
|
for (var key in allRowMap) {
|
|
var row = allRowMap[key];
|
|
var draftState = row._draftState;
|
|
|
|
switch (draftState) {
|
|
case 'add':
|
|
var addRow = cloneRow(row);
|
|
delete addRow._isNew;
|
|
delete addRow._draftState;
|
|
delete addRow._originData;
|
|
delete addRow._changedFields;
|
|
delete addRow._rowState;
|
|
addRows.push(addRow);
|
|
break;
|
|
case 'update':
|
|
var updateRow = cloneRow(row);
|
|
delete updateRow._isNew;
|
|
delete updateRow._draftState;
|
|
delete updateRow._originData;
|
|
delete updateRow._changedFields;
|
|
delete updateRow._rowState;
|
|
updateRows.push(updateRow);
|
|
break;
|
|
case 'delete':
|
|
var deleteRow = cloneRow(row);
|
|
delete deleteRow._isNew;
|
|
delete deleteRow._draftState;
|
|
delete deleteRow._originData;
|
|
delete deleteRow._changedFields;
|
|
delete deleteRow._rowState;
|
|
deleteRows.push(deleteRow);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return {
|
|
addRows: addRows,
|
|
updateRows: updateRows,
|
|
deleteRows: deleteRows
|
|
};
|
|
}
|
|
|
|
function getRowsByState(stateFilter) {
|
|
var result = [];
|
|
for (var key in allRowMap) {
|
|
var row = allRowMap[key];
|
|
if (row._draftState === stateFilter) {
|
|
result.push(cloneRow(row));
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
function getSelectedRowIds() {
|
|
var ids = [];
|
|
for (var key in selectionMap) {
|
|
if (selectionMap[key] === true) {
|
|
var row = allRowMap[key];
|
|
if (!row || row._draftState !== 'delete') {
|
|
ids.push(key);
|
|
}
|
|
}
|
|
}
|
|
return ids;
|
|
}
|
|
|
|
function getSelectedRows() {
|
|
var rows = [];
|
|
for (var key in selectionMap) {
|
|
if (selectionMap[key] === true) {
|
|
var row = allRowMap[key];
|
|
if (row) {
|
|
rows.push(cloneRow(row));
|
|
}
|
|
}
|
|
}
|
|
return rows;
|
|
}
|
|
|
|
function getValidSelectedRows(currentPageRows) {
|
|
var rows = [];
|
|
|
|
if (isAllChecked && currentPageRows && currentPageRows.length > 0) {
|
|
for (var i = 0; i < currentPageRows.length; i++) {
|
|
var row = currentPageRows[i];
|
|
var key = getRowKey(row);
|
|
|
|
if (!exclusionMap[key]) {
|
|
var cachedRow = allRowMap[key];
|
|
if (cachedRow && cachedRow._draftState !== 'delete') {
|
|
rows.push(cloneRow(cachedRow));
|
|
} else if (!cachedRow && row._draftState !== 'delete') {
|
|
rows.push(cloneRow(row));
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
for (var key in selectionMap) {
|
|
if (selectionMap[key] === true) {
|
|
var row = allRowMap[key];
|
|
if (row && row._draftState !== 'delete') {
|
|
rows.push(cloneRow(row));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return rows;
|
|
}
|
|
|
|
function getExcludedRowIds() {
|
|
var ids = [];
|
|
for (var key in exclusionMap) {
|
|
if (exclusionMap[key] === true) {
|
|
ids.push(key);
|
|
}
|
|
}
|
|
return ids;
|
|
}
|
|
|
|
function getExcludedRows() {
|
|
var rows = [];
|
|
for (var key in exclusionMap) {
|
|
if (exclusionMap[key] === true) {
|
|
var row = allRowMap[key];
|
|
if (row && row._draftState !== 'delete') {
|
|
rows.push(cloneRow(row));
|
|
}
|
|
}
|
|
}
|
|
return rows;
|
|
}
|
|
|
|
function reset() {
|
|
allRowMap = {};
|
|
draftRowMap = {};
|
|
selectionMap = {};
|
|
exclusionMap = {};
|
|
isAllChecked = false;
|
|
isBatchDeleting = false;
|
|
}
|
|
|
|
return {
|
|
keyField: keyField,
|
|
cloneRow: cloneRow,
|
|
getRowKey: getRowKey,
|
|
setRowToCache: setRowToCache,
|
|
getRowFromCache: getRowFromCache,
|
|
removeRowFromCache: removeRowFromCache,
|
|
updateRowInCache: updateRowInCache,
|
|
markRowDeleted: markRowDeleted,
|
|
unmarkRowDeleted: unmarkRowDeleted,
|
|
setSelection: setSelection,
|
|
isSelected: isSelected,
|
|
setExclusion: setExclusion,
|
|
isExcluded: isExcluded,
|
|
clearAllSelections: clearAllSelections,
|
|
clearAllExclusions: clearAllExclusions,
|
|
applyDraftStateToRemoteRows: applyDraftStateToRemoteRows,
|
|
getRowsForSubmission: getRowsForSubmission,
|
|
getRowsByState: getRowsByState,
|
|
getSelectedRowIds: getSelectedRowIds,
|
|
getSelectedRows: getSelectedRows,
|
|
getValidSelectedRows: getValidSelectedRows,
|
|
getExcludedRowIds: getExcludedRowIds,
|
|
getExcludedRows: getExcludedRows,
|
|
|
|
isAllChecked: function () { return isAllChecked; },
|
|
setAllChecked: function (value) {
|
|
isAllChecked = value;
|
|
if (value) clearAllSelections();
|
|
},
|
|
|
|
isBatchDeleting: function () { return isBatchDeleting; },
|
|
setBatchDeleting: function (value) {
|
|
if (!value && isBatchDeleting) {
|
|
for (var key in allRowMap) {
|
|
var row = allRowMap[key];
|
|
if (row._draftState === 'delete' && !exclusionMap[key]) {
|
|
if (row._originData) {
|
|
var originState = row._originData._draftState;
|
|
row._draftState = originState || null;
|
|
row._changedFields = row._originData._changedFields || [];
|
|
|
|
for (var field in row._originData) {
|
|
if (field.indexOf('_') !== 0) {
|
|
row[field] = row._originData[field];
|
|
}
|
|
}
|
|
} else {
|
|
row._draftState = null;
|
|
row._changedFields = [];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
isBatchDeleting = value;
|
|
},
|
|
|
|
getInsertRows: function () { return getRowsByState('add'); },
|
|
getUpdateRows: function () { return getRowsByState('update'); },
|
|
getDeleteRows: function () { return getRowsByState('delete'); },
|
|
|
|
reset: reset
|
|
};
|
|
}
|
|
|
|
// ==================== createDataGridManager(导出模块)====================
|
|
|
|
function createDataGridManager(config) {
|
|
var $ = window.jQuery;
|
|
|
|
var DEFAULT_CONFIG = {
|
|
gridId: "feegrid",
|
|
keyField: "subid",
|
|
pageSize: 50,
|
|
viewName: "",
|
|
searchUrl: "jsp/searchdatapagenew.jsp",
|
|
orderField: "b_id",
|
|
baseSearchCondition: null,
|
|
searchCondition: null,
|
|
pageList: [50, 100, 200],
|
|
rowStateStyles: {
|
|
add: "background-color: #f6ffed;",
|
|
update: "background-color: #fffbe6;",
|
|
delete: "background-color: #fff1f0;",
|
|
},
|
|
selectAllBtn: "#btn_select_all",
|
|
selectAllText: "全部选中",
|
|
unselectAllText: "全部反选",
|
|
userid: "",
|
|
customDatagridOptions: null,
|
|
ajaxTimeout: 30000,
|
|
onLoadError: null,
|
|
onLoadSuccess: null,
|
|
onAfterEdit: null,
|
|
onSelectionChange: null,
|
|
pagerId: null,
|
|
};
|
|
|
|
var options = $.extend(true, {}, DEFAULT_CONFIG, config);
|
|
|
|
var state = {
|
|
cacheManager: null,
|
|
editIndex: undefined,
|
|
isLoading: false,
|
|
pagerId: null,
|
|
requestVersion: 0,
|
|
isFirstLoad: true,
|
|
isSyncing: false,
|
|
pagination: {
|
|
pageSize: options.pageSize,
|
|
pageNumber: 1,
|
|
remoteTotal: 0,
|
|
}
|
|
};
|
|
|
|
_initCacheManager();
|
|
_initGrid();
|
|
|
|
function _initCacheManager() {
|
|
state.cacheManager = createGlobalCacheManager({
|
|
keyField: options.keyField
|
|
});
|
|
}
|
|
|
|
function _getPagerId() {
|
|
if (!state.pagerId) {
|
|
state.pagerId = options.pagerId || (options.gridId + "_pager");
|
|
}
|
|
return state.pagerId;
|
|
}
|
|
|
|
function _setLoading() {
|
|
state.isLoading = true;
|
|
$("#" + options.gridId).datagrid("loading");
|
|
$("#" + _getPagerId())
|
|
.css({
|
|
"pointer-events": "none",
|
|
opacity: "0.6",
|
|
})
|
|
.pagination("loading");
|
|
}
|
|
|
|
function _clearLoading() {
|
|
state.isLoading = false;
|
|
$("#" + options.gridId).datagrid("loaded");
|
|
$("#" + _getPagerId())
|
|
.css({
|
|
"pointer-events": "",
|
|
opacity: "",
|
|
})
|
|
.pagination("loaded");
|
|
}
|
|
|
|
function _syncGridChecks() {
|
|
var rows = $("#" + options.gridId).datagrid("getRows");
|
|
var cm = state.cacheManager;
|
|
|
|
state.isSyncing = true;
|
|
|
|
for (var i = 0; i < rows.length; i++) {
|
|
var row = rows[i];
|
|
var key = cm.getRowKey(row);
|
|
var shouldCheck = false;
|
|
|
|
if (cm.isAllChecked()) {
|
|
shouldCheck = !cm.isExcluded(key);
|
|
} else {
|
|
shouldCheck = cm.isSelected(key);
|
|
}
|
|
|
|
if (shouldCheck) {
|
|
$("#" + options.gridId).datagrid("checkRow", i);
|
|
} else {
|
|
$("#" + options.gridId).datagrid("uncheckRow", i);
|
|
}
|
|
}
|
|
|
|
state.isSyncing = false;
|
|
}
|
|
|
|
function _handleRowStyles() {
|
|
$(".datagrid-body tr").each(function () {
|
|
var rowIndex = $(this).attr("datagrid-row-index");
|
|
if (rowIndex !== undefined) {
|
|
var row = $("#" + options.gridId).datagrid("getRows")[parseInt(rowIndex)];
|
|
if (row && row._draftState === 'delete') {
|
|
$(this).addClass("datagrid-row-delete");
|
|
} else {
|
|
$(this).removeClass("datagrid-row-delete");
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
function buildFinalCondition() {
|
|
var parts = [];
|
|
|
|
if (options.baseSearchCondition) {
|
|
parts.push(options.baseSearchCondition);
|
|
}
|
|
|
|
if (options.searchCondition) {
|
|
parts.push(options.searchCondition);
|
|
}
|
|
|
|
return parts.join(" AND ");
|
|
}
|
|
|
|
function _renderPage(pageData, total, pageNumber, pageSize) {
|
|
$("#" + options.gridId).datagrid("loadData", pageData);
|
|
$("#" + _getPagerId()).pagination("refresh", {
|
|
total: total,
|
|
pageNumber: pageNumber,
|
|
pageSize: pageSize,
|
|
});
|
|
}
|
|
|
|
function _refresh(mode) {
|
|
switch (mode) {
|
|
case "full":
|
|
state.pagination.pageNumber = 1;
|
|
state.pagination.remoteTotal = 0;
|
|
loadPage(1);
|
|
break;
|
|
case "page":
|
|
refreshCurrentPage();
|
|
break;
|
|
case "display":
|
|
default:
|
|
refreshDisplay();
|
|
break;
|
|
}
|
|
}
|
|
|
|
function loadPage(pageNumber) {
|
|
_setLoading();
|
|
|
|
var pageSize = state.pagination.pageSize;
|
|
var searchCondition = buildFinalCondition();
|
|
var currentRequestVersion = ++state.requestVersion;
|
|
var insertRows = state.cacheManager.getInsertRows();
|
|
|
|
if (!searchCondition) {
|
|
var pageData = [];
|
|
if (insertRows.length > 0) {
|
|
var startInInsert = (pageNumber - 1) * pageSize;
|
|
var endInInsert = startInInsert + pageSize;
|
|
pageData = insertRows.slice(startInInsert, endInInsert);
|
|
}
|
|
|
|
var totalPages = Math.ceil(insertRows.length / pageSize);
|
|
if (pageNumber > totalPages && insertRows.length > 0) {
|
|
pageNumber = Math.max(1, totalPages);
|
|
var startInInsert = (pageNumber - 1) * pageSize;
|
|
var endInInsert = startInInsert + pageSize;
|
|
pageData = insertRows.slice(startInInsert, endInInsert);
|
|
}
|
|
|
|
state.pagination.pageNumber = pageNumber;
|
|
_renderPage(pageData, insertRows.length, pageNumber, pageSize);
|
|
_clearLoading();
|
|
return;
|
|
}
|
|
|
|
var remoteTotal = state.pagination.remoteTotal;
|
|
var startIndex = (pageNumber - 1) * pageSize;
|
|
var endIndex = startIndex + pageSize;
|
|
|
|
if (insertRows.length > 0 && startIndex >= remoteTotal) {
|
|
var insertStart = startIndex - remoteTotal;
|
|
var insertEnd = endIndex - remoteTotal;
|
|
var pageData = insertRows.slice(insertStart, insertEnd);
|
|
|
|
var totalCount = remoteTotal + insertRows.length;
|
|
|
|
state.pagination.pageNumber = pageNumber;
|
|
_renderPage(pageData, totalCount, pageNumber, pageSize);
|
|
_clearLoading();
|
|
return;
|
|
}
|
|
|
|
var searchParam = {
|
|
viewname: options.viewName,
|
|
searchcondition: searchCondition,
|
|
userid: options.userid,
|
|
orderfield: options.orderField,
|
|
keyfield: options.keyField,
|
|
page: pageNumber,
|
|
rows: pageSize,
|
|
};
|
|
|
|
$.ajax({
|
|
type: "post",
|
|
url: options.searchUrl,
|
|
cache: false,
|
|
data: searchParam,
|
|
dataType: "json",
|
|
timeout: options.ajaxTimeout,
|
|
success: function (result) {
|
|
if (currentRequestVersion !== state.requestVersion) {
|
|
return;
|
|
}
|
|
|
|
var remoteRows = state.cacheManager.applyDraftStateToRemoteRows(result.rows);
|
|
remoteTotal = result.total;
|
|
|
|
var totalCount = remoteTotal + insertRows.length;
|
|
var totalPages = Math.ceil(totalCount / pageSize);
|
|
|
|
if (pageNumber > totalPages) {
|
|
pageNumber = Math.max(1, totalPages);
|
|
}
|
|
|
|
startIndex = (pageNumber - 1) * pageSize;
|
|
endIndex = startIndex + pageSize;
|
|
|
|
var pageData = [];
|
|
|
|
if (endIndex <= remoteTotal) {
|
|
pageData = remoteRows;
|
|
} else if (startIndex >= remoteTotal) {
|
|
var insertStart = startIndex - remoteTotal;
|
|
var insertEnd = endIndex - remoteTotal;
|
|
pageData = insertRows.slice(insertStart, insertEnd);
|
|
} else {
|
|
var remotePart = remoteRows.slice(startIndex - (pageNumber - 1) * pageSize);
|
|
var insertPart = insertRows.slice(0, endIndex - remoteTotal);
|
|
pageData = remotePart.concat(insertPart);
|
|
}
|
|
|
|
state.pagination.remoteTotal = remoteTotal;
|
|
state.pagination.pageNumber = pageNumber;
|
|
|
|
_renderPage(pageData, totalCount, pageNumber, pageSize);
|
|
},
|
|
error: function (xhr, status, error) {
|
|
if (currentRequestVersion !== state.requestVersion) {
|
|
return;
|
|
}
|
|
|
|
if (insertRows.length > 0) {
|
|
var startInInsert = (pageNumber - 1) * pageSize;
|
|
var endInInsert = startInInsert + pageSize;
|
|
var pageData = insertRows.slice(startInInsert, endInInsert);
|
|
_renderPage(pageData, insertRows.length, pageNumber, pageSize);
|
|
}
|
|
|
|
if (typeof options.onLoadError === "function") {
|
|
options.onLoadError(xhr, status, error);
|
|
} else {
|
|
console.log("分页加载失败: " + status);
|
|
}
|
|
},
|
|
complete: function () {
|
|
if (currentRequestVersion === state.requestVersion) {
|
|
_clearLoading();
|
|
}
|
|
},
|
|
});
|
|
}
|
|
|
|
function refreshCurrentPage() {
|
|
var currentPage = state.pagination.pageNumber;
|
|
loadPage(currentPage);
|
|
}
|
|
|
|
function refreshDisplay() {
|
|
var currentRows = $("#" + options.gridId).datagrid("getRows");
|
|
var cm = state.cacheManager;
|
|
|
|
for (var i = 0; i < currentRows.length; i++) {
|
|
var row = currentRows[i];
|
|
var key = cm.getRowKey(row);
|
|
var cachedRow = cm.getRowFromCache(key);
|
|
|
|
if (cachedRow) {
|
|
row._draftState = cachedRow._draftState;
|
|
row._rowState = cachedRow._draftState;
|
|
}
|
|
}
|
|
|
|
$("#" + options.gridId).datagrid("loadData", currentRows);
|
|
|
|
if (!cm.isAllChecked()) {
|
|
$("#" + options.gridId).datagrid("clearChecked");
|
|
}
|
|
|
|
_handleRowStyles();
|
|
_triggerCallback("onSelectionChange");
|
|
}
|
|
|
|
function refreshAfterDelete() {
|
|
var pageSize = state.pagination.pageSize;
|
|
var remoteTotal = state.pagination.remoteTotal;
|
|
var insertRows = state.cacheManager.getInsertRows();
|
|
var deleteRows = state.cacheManager.getDeleteRows();
|
|
var totalPages = Math.ceil((remoteTotal + insertRows.length) / pageSize);
|
|
var currentPage = state.pagination.pageNumber;
|
|
|
|
if (currentPage > totalPages && totalPages > 0) {
|
|
state.pagination.pageNumber = totalPages;
|
|
$("#" + _getPagerId()).pagination("select", totalPages);
|
|
} else if (remoteTotal === 0 && insertRows.length === 0) {
|
|
$("#" + options.gridId).datagrid("loadData", []);
|
|
$("#" + _getPagerId()).pagination("refresh", {
|
|
total: 0,
|
|
pageNumber: 1,
|
|
pageSize: pageSize,
|
|
});
|
|
} else {
|
|
loadPage(currentPage);
|
|
}
|
|
|
|
$("#" + options.gridId).datagrid("clearChecked");
|
|
_triggerCallback("onSelectionChange");
|
|
}
|
|
|
|
function refreshAfterUndo() {
|
|
var currentPage = state.pagination.pageNumber;
|
|
loadPage(currentPage);
|
|
}
|
|
|
|
function addInsertRows(rows) {
|
|
if (!$.isArray(rows)) rows = [rows];
|
|
var cm = state.cacheManager;
|
|
|
|
for (var i = 0; i < rows.length; i++) {
|
|
var row = rows[i];
|
|
var key = cm.getRowKey(row);
|
|
if (!cm.getRowFromCache(key)) {
|
|
cm.setRowToCache(row, true);
|
|
}
|
|
}
|
|
}
|
|
|
|
function removeInsertRow(row) {
|
|
var key = state.cacheManager.getRowKey(row);
|
|
state.cacheManager.removeRowFromCache(key);
|
|
}
|
|
|
|
function addDeleteRow(row) {
|
|
state.cacheManager.markRowDeleted(row);
|
|
}
|
|
|
|
function removeDeleteRow(row) {
|
|
state.cacheManager.unmarkRowDeleted(row);
|
|
refreshAfterUndo();
|
|
}
|
|
|
|
function addUpdateRow(row) {
|
|
state.cacheManager.updateRowInCache(row);
|
|
}
|
|
|
|
function deleteSelectedRows(canDeleteCallback) {
|
|
var currentPageRows = $("#" + options.gridId).datagrid("getRows");
|
|
var selectedRows = state.cacheManager.getValidSelectedRows(currentPageRows);
|
|
var cm = state.cacheManager;
|
|
|
|
if (selectedRows.length === 0) {
|
|
$.messager.alert("提示", "请选择要删除的行(已标记删除的行请使用「撤销删除」)", "warning");
|
|
return false;
|
|
}
|
|
|
|
if (canDeleteCallback) {
|
|
for (var i = selectedRows.length - 1; i >= 0; i--) {
|
|
var row = selectedRows[i];
|
|
var result = canDeleteCallback(row);
|
|
if (result !== true) {
|
|
$.messager.alert("提示", result || "该记录不能删除!", "warning");
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
var hasInsertDelete = false;
|
|
var hasRemoteDelete = false;
|
|
|
|
for (var i = selectedRows.length - 1; i >= 0; i--) {
|
|
var row = selectedRows[i];
|
|
var wasNew = cm.getRowFromCache(cm.getRowKey(row))?._isNew;
|
|
|
|
if (cm.markRowDeleted(row)) {
|
|
hasInsertDelete = true;
|
|
} else {
|
|
hasRemoteDelete = true;
|
|
}
|
|
}
|
|
|
|
if (cm.isAllChecked()) {
|
|
cm.setBatchDeleting(true);
|
|
}
|
|
|
|
if (hasInsertDelete) {
|
|
refreshAfterDelete();
|
|
} else if (hasRemoteDelete) {
|
|
refreshDisplay();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
function undoDeleteSelectedRows() {
|
|
var cm = state.cacheManager;
|
|
var pageRows = $("#" + options.gridId).datagrid("getRows");
|
|
var targets = [];
|
|
|
|
var selectedRows = cm.getSelectedRows();
|
|
var selKeys = {};
|
|
for (var sk = 0; sk < selectedRows.length; sk++) {
|
|
selKeys[cm.getRowKey(selectedRows[sk])] = true;
|
|
}
|
|
|
|
var hasSelectionOnPage = false;
|
|
for (var hp = 0; hp < pageRows.length; hp++) {
|
|
if (selKeys[cm.getRowKey(pageRows[hp])]) {
|
|
hasSelectionOnPage = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (cm.isAllChecked() && cm.isBatchDeleting()) {
|
|
for (var u = 0; u < pageRows.length; u++) {
|
|
var row = pageRows[u];
|
|
var key = cm.getRowKey(row);
|
|
if (row._draftState === 'delete' && !cm.isExcluded(key)) {
|
|
targets.push(row);
|
|
}
|
|
}
|
|
} else if (!hasSelectionOnPage) {
|
|
for (var u = 0; u < pageRows.length; u++) {
|
|
if (pageRows[u]._draftState === 'delete') {
|
|
targets.push(pageRows[u]);
|
|
}
|
|
}
|
|
} else {
|
|
for (var v = 0; v < pageRows.length; v++) {
|
|
var pr = pageRows[v];
|
|
if (pr._draftState === 'delete' && selKeys[cm.getRowKey(pr)]) {
|
|
targets.push(pr);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (targets.length === 0) {
|
|
$.messager.alert("提示", "当前页没有可撤销的删除行", "warning");
|
|
return false;
|
|
}
|
|
|
|
var restoredRowIndexes = [];
|
|
for (var w = 0; w < targets.length; w++) {
|
|
var row = targets[w];
|
|
if (row._draftState !== 'delete') {
|
|
continue;
|
|
}
|
|
var rowIndex = $("#" + options.gridId).datagrid("getRowIndex", row);
|
|
cm.unmarkRowDeleted(row);
|
|
cm.setSelection(cm.getRowKey(row), true);
|
|
if (rowIndex >= 0) {
|
|
restoredRowIndexes.push(rowIndex);
|
|
}
|
|
}
|
|
|
|
cm.setBatchDeleting(false);
|
|
refreshAfterUndo();
|
|
|
|
for (var r = 0; r < restoredRowIndexes.length; r++) {
|
|
$("#" + options.gridId).datagrid("checkRow", restoredRowIndexes[r]);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
function toggleSelectAll() {
|
|
state.isSyncing = true;
|
|
var btn = $(options.selectAllBtn);
|
|
var cm = state.cacheManager;
|
|
|
|
if (cm.isAllChecked()) {
|
|
cm.setAllChecked(false);
|
|
cm.setBatchDeleting(false);
|
|
cm.clearAllExclusions();
|
|
cm.clearAllSelections();
|
|
$("#" + options.gridId).datagrid("clearChecked");
|
|
if (btn.length) btn.val(options.selectAllText);
|
|
} else {
|
|
cm.setAllChecked(true);
|
|
cm.clearAllExclusions();
|
|
var rows = $("#" + options.gridId).datagrid("getRows");
|
|
for (var i = 0; i < rows.length; i++) {
|
|
$("#" + options.gridId).datagrid("checkRow", i);
|
|
}
|
|
if (btn.length) btn.val(options.unselectAllText);
|
|
}
|
|
|
|
state.isSyncing = false;
|
|
_triggerCallback("onSelectionChange");
|
|
}
|
|
|
|
function clearSelection() {
|
|
var cm = state.cacheManager;
|
|
cm.setAllChecked(false);
|
|
cm.setBatchDeleting(false);
|
|
cm.clearAllExclusions();
|
|
cm.clearAllSelections();
|
|
$("#" + options.gridId).datagrid("clearChecked");
|
|
_triggerCallback("onSelectionChange");
|
|
}
|
|
|
|
function setAllChecked(value) {
|
|
var cm = state.cacheManager;
|
|
cm.setAllChecked(value);
|
|
if (value) cm.clearAllExclusions();
|
|
_syncGridChecks();
|
|
_triggerCallback("onSelectionChange");
|
|
}
|
|
|
|
function setSearchCondition(condition) {
|
|
options.searchCondition = condition;
|
|
}
|
|
|
|
function clearSearch() {
|
|
options.searchCondition = null;
|
|
}
|
|
|
|
function reload(newSearchCondition) {
|
|
if (newSearchCondition !== undefined) {
|
|
options.searchCondition = newSearchCondition;
|
|
}
|
|
state.pagination.pageNumber = 1;
|
|
state.pagination.remoteTotal = 0;
|
|
loadPage(1);
|
|
}
|
|
|
|
function resetSearch() {
|
|
options.searchCondition = null;
|
|
reload();
|
|
}
|
|
|
|
function _triggerCallback(callbackName) {
|
|
var callback = options[callbackName];
|
|
if (typeof callback === "function") {
|
|
var args = Array.prototype.slice.call(arguments, 1);
|
|
callback.apply(null, args);
|
|
}
|
|
}
|
|
|
|
function handleAfterEdit(rowIndex, row, changes) {
|
|
if (Object.keys(changes).length === 0) return;
|
|
|
|
var cm = state.cacheManager;
|
|
var key = cm.getRowKey(row);
|
|
var cachedRow = cm.getRowFromCache(key);
|
|
|
|
if (cachedRow && cachedRow._draftState === 'delete') {
|
|
return;
|
|
}
|
|
|
|
cm.updateRowInCache(row);
|
|
_triggerCallback("onAfterEdit", rowIndex, row, changes);
|
|
}
|
|
|
|
function handleRowCheck(index, row) {
|
|
var cm = state.cacheManager;
|
|
|
|
if (cm.isAllChecked()) {
|
|
cm.setExclusion(cm.getRowKey(row), false);
|
|
} else {
|
|
cm.setSelection(cm.getRowKey(row), true);
|
|
}
|
|
|
|
if (!state.isSyncing) {
|
|
_triggerCallback("onSelectionChange");
|
|
}
|
|
}
|
|
|
|
function handleRowUncheck(index, row) {
|
|
var cm = state.cacheManager;
|
|
|
|
if (cm.isAllChecked()) {
|
|
cm.setExclusion(cm.getRowKey(row), true);
|
|
} else {
|
|
cm.setSelection(cm.getRowKey(row), false);
|
|
}
|
|
|
|
if (!state.isSyncing) {
|
|
_triggerCallback("onSelectionChange");
|
|
}
|
|
}
|
|
|
|
function handleCheckAll() {
|
|
state.isSyncing = true;
|
|
var cm = state.cacheManager;
|
|
var rows = $("#" + options.gridId).datagrid("getRows");
|
|
for (var i = 0; i < rows.length; i++) {
|
|
var key = cm.getRowKey(rows[i]);
|
|
if (cm.isAllChecked()) {
|
|
cm.setExclusion(key, false);
|
|
} else {
|
|
cm.setSelection(key, true);
|
|
}
|
|
}
|
|
state.isSyncing = false;
|
|
_triggerCallback("onSelectionChange");
|
|
}
|
|
|
|
function handleUncheckAll() {
|
|
state.isSyncing = true;
|
|
var cm = state.cacheManager;
|
|
var rows = $("#" + options.gridId).datagrid("getRows");
|
|
for (var i = 0; i < rows.length; i++) {
|
|
var key = cm.getRowKey(rows[i]);
|
|
if (cm.isAllChecked()) {
|
|
cm.setExclusion(key, true);
|
|
} else {
|
|
cm.setSelection(key, false);
|
|
}
|
|
}
|
|
state.isSyncing = false;
|
|
_triggerCallback("onSelectionChange");
|
|
}
|
|
|
|
function handleLoadSuccess() {
|
|
$.messager.progress("close");
|
|
_syncGridChecks();
|
|
_handleRowStyles();
|
|
var rows = $("#" + options.gridId).datagrid("getRows");
|
|
_triggerCallback("onLoadSuccess", rows);
|
|
}
|
|
|
|
function reset() {
|
|
state.editIndex = undefined;
|
|
state.isLoading = false;
|
|
state.pagination = {
|
|
pageSize: options.pageSize,
|
|
pageNumber: 1,
|
|
remoteTotal: 0,
|
|
};
|
|
if (state.cacheManager) state.cacheManager.reset();
|
|
}
|
|
|
|
function _initGrid() {
|
|
var pagerId = _getPagerId();
|
|
var pagerSelector = "#" + pagerId;
|
|
|
|
var baseDatagridOptions = {
|
|
idField: options.keyField,
|
|
pageSize: options.pageSize,
|
|
rowStyler: function (index, row) {
|
|
var draftState = row._draftState;
|
|
|
|
if (!draftState && state.cacheManager) {
|
|
var key = state.cacheManager.getRowKey(row);
|
|
var cachedRow = state.cacheManager.getRowFromCache(key);
|
|
if (cachedRow) {
|
|
draftState = cachedRow._draftState;
|
|
}
|
|
}
|
|
|
|
var stateStyle = options.rowStateStyles[draftState] || options.rowStateStyles[row._rowState];
|
|
return stateStyle || "";
|
|
},
|
|
onLoadSuccess: handleLoadSuccess,
|
|
onAfterEdit: handleAfterEdit,
|
|
onCheckAll: handleCheckAll,
|
|
onUncheckAll: handleUncheckAll,
|
|
onCheck: handleRowCheck,
|
|
onUncheck: handleRowUncheck,
|
|
};
|
|
|
|
var datagridOptions = options.customDatagridOptions
|
|
? $.extend(true, {}, baseDatagridOptions, options.customDatagridOptions)
|
|
: baseDatagridOptions;
|
|
|
|
$("#" + options.gridId)
|
|
.datagrid(datagridOptions)
|
|
.datagrid("columnMoving");
|
|
|
|
$("#" + options.gridId)
|
|
.datagrid("getPanel")
|
|
.find(".datagrid-body")
|
|
.on("scroll.datagrid", function () {
|
|
if (state.editIndex !== undefined) {
|
|
$("#" + options.gridId).datagrid("endEdit", state.editIndex);
|
|
state.editIndex = undefined;
|
|
}
|
|
});
|
|
|
|
$(pagerSelector).pagination({
|
|
total: 0,
|
|
pageSize: options.pageSize,
|
|
pageNumber: 1,
|
|
pageList: options.pageList,
|
|
onSelectPage: function (pageNumber, pageSize) {
|
|
state.pagination.pageNumber = pageNumber;
|
|
state.pagination.pageSize = pageSize;
|
|
loadPage(pageNumber);
|
|
},
|
|
onChangePageSize: function (pageSize) {
|
|
state.pagination.pageNumber = 1;
|
|
state.pagination.pageSize = pageSize;
|
|
|
|
if (!state.cacheManager.isAllChecked()) {
|
|
$("#" + options.gridId).datagrid("clearChecked");
|
|
state.cacheManager.clearAllSelections();
|
|
}
|
|
|
|
_triggerCallback("onSelectionChange");
|
|
loadPage(1);
|
|
},
|
|
});
|
|
}
|
|
|
|
function setColumns(columns) {
|
|
$("#" + options.gridId).datagrid({
|
|
columns: [columns],
|
|
});
|
|
}
|
|
|
|
function isLoading() {
|
|
return state.isLoading;
|
|
}
|
|
|
|
function getPager() {
|
|
return $("#" + _getPagerId());
|
|
}
|
|
|
|
function getGrid() {
|
|
return $("#" + options.gridId);
|
|
}
|
|
|
|
function getRowsForSubmission() {
|
|
return state.cacheManager.getRowsForSubmission();
|
|
}
|
|
|
|
return {
|
|
setColumns: setColumns,
|
|
loadPage: loadPage,
|
|
refreshCurrentPage: refreshCurrentPage,
|
|
refreshDisplay: refreshDisplay,
|
|
refreshAfterDelete: refreshAfterDelete,
|
|
refreshAfterUndo: refreshAfterUndo,
|
|
|
|
addInsertRows: addInsertRows,
|
|
removeInsertRow: removeInsertRow,
|
|
addDeleteRow: addDeleteRow,
|
|
removeDeleteRow: removeDeleteRow,
|
|
addUpdateRow: addUpdateRow,
|
|
deleteSelectedRows: deleteSelectedRows,
|
|
undoDeleteSelectedRows: undoDeleteSelectedRows,
|
|
|
|
getValidSelectedRows: function () {
|
|
var currentPageRows = $("#" + options.gridId).datagrid("getRows");
|
|
return state.cacheManager.getValidSelectedRows(currentPageRows);
|
|
},
|
|
getSelectedRows: function () {
|
|
return state.cacheManager.getSelectedRows();
|
|
},
|
|
toggleSelectAll: toggleSelectAll,
|
|
clearSelection: clearSelection,
|
|
isAllChecked: function () {
|
|
console.log("===1===")
|
|
return state.cacheManager.isAllChecked();
|
|
},
|
|
setAllChecked: setAllChecked,
|
|
|
|
getInsertRows: function () {
|
|
return state.cacheManager.getInsertRows();
|
|
},
|
|
getUpdateRows: function () {
|
|
return state.cacheManager.getUpdateRows();
|
|
},
|
|
getDeleteRows: function () {
|
|
return state.cacheManager.getDeleteRows();
|
|
},
|
|
getExcludedRows: function () {
|
|
return state.cacheManager.getExcludedRows();
|
|
},
|
|
|
|
getRowsForSubmission: getRowsForSubmission,
|
|
|
|
getCacheManager: function () {
|
|
return state.cacheManager;
|
|
},
|
|
|
|
setSearchCondition: setSearchCondition,
|
|
clearSearch: clearSearch,
|
|
reload: reload,
|
|
resetSearch: resetSearch,
|
|
|
|
isLoading: isLoading,
|
|
getPager: getPager,
|
|
getGrid: getGrid,
|
|
reset: reset,
|
|
};
|
|
}
|
|
|
|
window.createDataGridManager = createDataGridManager;
|
|
})(window); |