$(document).ready(function() {
autoFlashHeight();
const RangeType = {
unitType: 1,
unit: 2,
user: 3,
};
const typeIndex = {};
const unitIndex = {};
const userIndex = {};
dataRangeTree.forEach(type => {
typeIndex[Number(type.id)] = type;
type.units.forEach(unit => {
unit.parentTypeId = Number(type.id);
unitIndex[Number(unit.id)] = unit;
unit.users.forEach(user => {
user.parentTypeId = Number(type.id);
user.parentUnitId = Number(unit.id);
userIndex[Number(user.id)] = user;
});
});
});
dataRangeUnassignedUsers.forEach(user => {
user.parentTypeId = Number(user.account_group) || 0;
userIndex[Number(user.id)] = user;
});
const makeSelection = function(config) {
return {
unitTypeIds: new Set((config.unit_type_ids || []).map(Number)),
unitIds: new Set((config.unit_ids || []).map(Number)),
userIds: new Set((config.user_ids || []).map(Number)),
};
};
const cloneSelection = function(source) {
return {
unitTypeIds: new Set(Array.from(source.unitTypeIds)),
unitIds: new Set(Array.from(source.unitIds)),
userIds: new Set(Array.from(source.userIds)),
};
};
let savedSelection = makeSelection(dataRangeConfig);
let savedConfigured = Boolean(dataRangeConfig.configured);
let currentSelection = cloneSelection(savedSelection);
const escapeHtml = function(value) {
return $('
').text(value === undefined || value === null ? '' : value).html();
};
const containsKeyword = function(value, keyword) {
return !keyword || String(value || '').toLowerCase().indexOf(keyword) >= 0;
};
const getSelectionSet = function(rangeType) {
if (rangeType === RangeType.unitType) return currentSelection.unitTypeIds;
if (rangeType === RangeType.unit) return currentSelection.unitIds;
return currentSelection.userIds;
};
const getSelectionSetFrom = function(selection, rangeType) {
if (rangeType === RangeType.unitType) return selection.unitTypeIds;
if (rangeType === RangeType.unit) return selection.unitIds;
return selection.userIds;
};
const getRangeName = function(rangeType, targetId) {
let node;
if (rangeType === RangeType.unitType) node = typeIndex[targetId];
if (rangeType === RangeType.unit) node = unitIndex[targetId];
if (rangeType === RangeType.user) node = userIndex[targetId];
return node ? node.name : '';
};
const getRangeTitle = function(rangeType) {
if (rangeType === RangeType.unitType) return '单位类型';
if (rangeType === RangeType.unit) return '单位';
return '用户';
};
const removeTypeDescendants = function(typeId) {
const type = typeIndex[typeId];
if (!type) return;
type.units.forEach(unit => {
currentSelection.unitIds.delete(Number(unit.id));
unit.users.forEach(user => currentSelection.userIds.delete(Number(user.id)));
});
dataRangeUnassignedUsers.forEach(user => {
if (Number(user.parentTypeId) === Number(typeId)) currentSelection.userIds.delete(Number(user.id));
});
};
const removeUnitDescendants = function(unitId) {
const unit = unitIndex[unitId];
if (!unit) return;
unit.users.forEach(user => currentSelection.userIds.delete(Number(user.id)));
};
const renderCheckbox = function(rangeType, targetId, disabled) {
const checked = getSelectionSet(rangeType).has(Number(targetId)) ? ' checked' : '';
const disabledAttr = disabled ? ' disabled' : '';
return `
`;
};
const renderNode = function(options) {
const indent = options.level * 20;
const toggle = options.hasChildren
? '
'
: '
';
const checkbox = options.selectable === false ? '' : renderCheckbox(options.rangeType, options.targetId, options.disabled);
const icon = options.rangeType === RangeType.user
? '
'
: '
';
const extra = options.extra ? `
${escapeHtml(options.extra)}` : '';
return `
${toggle}${checkbox}${icon}${escapeHtml(options.name)}${extra}
`;
};
const renderTree = function() {
const keyword = $('#data-range-keyword').val().trim().toLowerCase();
const html = [];
dataRangeTree.forEach(type => {
const typeMatch = containsKeyword(type.name, keyword);
const visibleUnits = [];
type.units.forEach(unit => {
const unitMatch = containsKeyword(unit.name, keyword);
const users = typeMatch || unitMatch ? unit.users : unit.users.filter(user => {
return containsKeyword(user.name, keyword) || containsKeyword(user.role, keyword);
});
if (!keyword || typeMatch || unitMatch || users.length > 0) visibleUnits.push({ unit, users });
});
if (keyword && !typeMatch && visibleUnits.length === 0) return;
html.push('
');
html.push(renderNode({
level: 0,
hasChildren: visibleUnits.length > 0,
rangeType: RangeType.unitType,
targetId: Number(type.id),
name: type.name,
}));
html.push('
');
visibleUnits.forEach(item => {
const typeSelected = currentSelection.unitTypeIds.has(Number(type.id));
html.push('
');
html.push(renderNode({
level: 1,
hasChildren: item.users.length > 0,
rangeType: RangeType.unit,
targetId: Number(item.unit.id),
name: item.unit.name,
disabled: typeSelected,
}));
html.push('
');
item.users.forEach(user => {
const unitSelected = currentSelection.unitIds.has(Number(item.unit.id));
html.push(renderNode({
level: 2,
hasChildren: false,
rangeType: RangeType.user,
targetId: Number(user.id),
name: user.name,
extra: user.role,
disabled: typeSelected || unitSelected,
}));
});
html.push('
');
});
html.push('
');
});
const otherUsers = keyword ? dataRangeUnassignedUsers.filter(user => {
return containsKeyword(user.name, keyword) || containsKeyword(user.company, keyword) || containsKeyword(user.role, keyword);
}) : dataRangeUnassignedUsers;
if (otherUsers.length > 0) {
html.push('
');
html.push(renderNode({ level: 0, hasChildren: true, selectable: false, name: '未关联单位用户' }));
html.push('
');
otherUsers.forEach(user => {
const typeSelected = currentSelection.unitTypeIds.has(Number(user.parentTypeId));
html.push(renderNode({
level: 1,
hasChildren: false,
rangeType: RangeType.user,
targetId: Number(user.id),
name: user.name,
extra: user.company || user.role,
disabled: typeSelected,
}));
});
html.push('
');
}
if (html.length === 0) html.push('
没有匹配的数据
');
$('#data-range-tree').html(html.join(''));
};
const renderSelected = function() {
const html = [];
const appendItems = function(rangeType, ids) {
Array.from(ids).sort((a, b) => a - b).forEach(targetId => {
html.push('
');
html.push(`
${getRangeTitle(rangeType)}`);
html.push(`
${escapeHtml(getRangeName(rangeType, targetId))}`);
html.push(`
`);
html.push('
');
});
};
appendItems(RangeType.unitType, currentSelection.unitTypeIds);
appendItems(RangeType.unit, currentSelection.unitIds);
appendItems(RangeType.user, currentSelection.userIds);
const total = currentSelection.unitTypeIds.size + currentSelection.unitIds.size + currentSelection.userIds.size;
if (total === 0) html.push('
暂未选择范围
');
$('#data-range-selected-count').text(total);
$('#selected-unit-type-count').text(currentSelection.unitTypeIds.size);
$('#selected-unit-count').text(currentSelection.unitIds.size);
$('#selected-user-count').text(currentSelection.userIds.size);
$('#data-range-selected-list').html(html.join(''));
};
const renderSummary = function() {
if (!savedConfigured) {
$('#data-range-summary').text('当前未配置数据范围,默认可选择当前子项目全部启用成员。');
return;
}
$('#data-range-summary').text(
`已设置:单位类型 ${savedSelection.unitTypeIds.size} 项,单位 ${savedSelection.unitIds.size} 项,具体用户 ${savedSelection.userIds.size} 项。`
);
};
const renderMainSelection = function() {
const html = [];
const appendItems = function(rangeType, ids) {
Array.from(ids).sort((a, b) => a - b).forEach(targetId => {
const rangeName = getRangeName(rangeType, targetId);
if (!rangeName) return;
html.push(`
`);
html.push(`${escapeHtml(rangeName)}`);
html.push(``);
html.push('');
});
};
appendItems(RangeType.unitType, savedSelection.unitTypeIds);
appendItems(RangeType.unit, savedSelection.unitIds);
appendItems(RangeType.user, savedSelection.userIds);
$('#data-range-value-list').html(html.join(''));
};
const selectionToRanges = function(selection) {
const ranges = [];
const appendRanges = function(rangeType, ids) {
ids.forEach(targetId => ranges.push({ range_type: rangeType, target_id: targetId }));
};
appendRanges(RangeType.unitType, selection.unitTypeIds);
appendRanges(RangeType.unit, selection.unitIds);
appendRanges(RangeType.user, selection.userIds);
return ranges;
};
let saving = false;
const saveSelection = function(selection, successCallback) {
if (saving) return;
saving = true;
$('#save-data-range').prop('disabled', true);
postData(`/sp/${dataRangeSpid}/setting/user/data-range/update`, {
module_key: dataRangeModuleKey,
ranges: selectionToRanges(selection),
}, function(result) {
const config = result || {
configured: selectionToRanges(selection).length > 0,
unit_type_ids: Array.from(selection.unitTypeIds),
unit_ids: Array.from(selection.unitIds),
user_ids: Array.from(selection.userIds),
};
savedSelection = makeSelection(config);
savedConfigured = Boolean(config.configured);
saving = false;
$('#save-data-range').prop('disabled', false);
renderMainSelection();
renderSummary();
if (successCallback) successCallback();
}, function() {
saving = false;
$('#save-data-range').prop('disabled', false);
});
};
const refreshModal = function() {
renderTree();
renderSelected();
};
$('#open-data-range-modal').on('click keydown', function(event) {
if ($(event.target).closest('.remove-main-data-range').length > 0) return;
if (event.type === 'keydown' && event.keyCode !== 13 && event.keyCode !== 32) return;
event.preventDefault();
currentSelection = cloneSelection(savedSelection);
$('#data-range-keyword').val('');
refreshModal();
$('#data-range-modal').modal('show');
});
$('body').on('click', '.remove-main-data-range', function(event) {
event.preventDefault();
event.stopPropagation();
if (saving) return;
const rangeType = Number($(this).attr('data-range-type'));
const targetId = Number($(this).attr('data-target-id'));
const nextSelection = cloneSelection(savedSelection);
getSelectionSetFrom(nextSelection, rangeType).delete(targetId);
saveSelection(nextSelection, function() {
toastr.success('授权用户范围已移除');
});
});
$('#data-range-search').click(renderTree);
$('#data-range-keyword').on('keydown', function(event) {
if (event.keyCode === 13) {
event.preventDefault();
renderTree();
}
});
$('#data-range-keyword').on('input', renderTree);
$('body').on('click', '.data-range-toggle:not(.empty)', function() {
const children = $(this).parent().next('.data-range-children');
children.toggleClass('collapsed');
$('i', this).toggleClass('fa-caret-down fa-caret-right');
});
$('body').on('change', '.data-range-check', function() {
const rangeType = Number($(this).attr('data-range-type'));
const targetId = Number($(this).attr('data-target-id'));
const selection = getSelectionSet(rangeType);
if (this.checked) {
selection.add(targetId);
if (rangeType === RangeType.unitType) removeTypeDescendants(targetId);
if (rangeType === RangeType.unit) removeUnitDescendants(targetId);
} else {
selection.delete(targetId);
}
refreshModal();
});
$('body').on('click', '.remove-data-range', function() {
const rangeType = Number($(this).attr('data-range-type'));
const targetId = Number($(this).attr('data-target-id'));
getSelectionSet(rangeType).delete(targetId);
refreshModal();
});
$('#save-data-range').click(function() {
saveSelection(currentSelection, function() {
$('#data-range-modal').modal('hide');
toastr.success('数据范围保存成功');
});
});
renderMainSelection();
renderSummary();
});