* Code for task #89847.

This commit is contained in:
hufangzhou
2023-04-06 13:33:46 +08:00
parent bba7fa92d7
commit 39c6457675
4 changed files with 300 additions and 80 deletions
+43
View File
@@ -1010,4 +1010,47 @@ class group extends control
return print(html::select('actions[]', $privList, '', "multiple='multiple' class='form-control'"));
}
/**
* AJAX: Get priv's dependent priv list.
*
* @param string $privIdList
* @access public
* @return bool
*/
public function ajaxGetDependentPrivs($privIdList)
{
$relatedPrivs = $this->dao->select('t1.relationPriv,t2.parent,t2.module,t2.method,t3.`key`,t3.value')->from(TABLE_PRIVRELATION)->alias('t1')
->leftJoin(TABLE_PRIV)->alias('t2')->on('t1.relationPriv=t2.id')
->leftJoin(TABLE_PRIVLANG)->alias('t3')->on('t2.relationPriv=t3.objectID')
->leftJoin(TABLE_PRIVMANAGER)->alias('t4')->on('t2.parent=t4.id')
->where('t1.priv')->in($privIdList)
->andWhere('t1.relationPriv')->notin($privIdList)
->andWhere('t2.type')->eq('depend')
->andWhere('t3.objectType')->eq('priv')
->andWhere('t1.edition')->like("%,{$this->config->edition},%")
->andWhere('t1.vision')->like("%,{$this->config->vision},%")
->fetchAll('relationPriv');
if(empty($relatedPrivs)) return print('');
$modulePairs = $this->group->getPrivManagerPairs('module');
$managerList = $this->dao->select('*')->from(TABLE_PRIVMANAGER)->fetchAll('id');
$relatedPrivs = $this->group->transformPrivLang($relatedPrivs);
$privList = array('depend' => array(), 'recommend' => array());
foreach($relatedPrivs as $privID => $relatedPriv)
{
$module = $relatedPriv->module;
if(!isset($privList['depend'][$module])) $privList[$type][$module] = array();
$moduleCode = $managerList[$relatedPriv->parent]->type == 'package' ? $managerList[$managerList[$relatedPriv->parent]->parent]->code : $managerList[$relatedPriv->parent]->code;
$privList['depend'][$module]['title'] = $modulePairs[$moduleCode];
$privList['depend'][$module]['module'] = $moduleCode;
$privList['depend'][$module]['children'][] = array('title' => $relatedPriv->name, 'relationPriv' => $privID);
}
$privList[$type] = array_values($privList[$type]);
return print(json_encode($privList));
}
}
+14
View File
@@ -1,3 +1,17 @@
.mt-m {margin-top: 16px;}
.flex-center {display: flex; justify-content: center; align-items: center;}
#mainContent {display: flex; gap: 16px; height: calc(100vh - 120px);}
#mainContent > .main {flex: 1 1 75%; overflow-y: auto; min-height: 480px;}
#mainContent > .side {flex: 1 1 25%;}
.priv-panel {background: #fff; padding: 10px; box-shadow: 0 1px 1px rgb(0 0 0 / 5%), 0 2px 6px 0 rgb(0 0 0 / 5%);}
.priv-panel > .panel-content {height: calc(50vh - 160px); overflow-y: auto; min-height: 140px;}
.priv-panel > .panel-bottom {padding-top: 20px;}
/* tree */
.tree ul > li {display: inline-block; width: 50%;}
.priv-item > .icon {padding-left: 5px;}
.empty-tip {height: 100%;}
.table-bymodule select.form-control {height: 250px;}
.group-item {display: block; width: 220px; float: left; font-size: 14px;}
.group-item .checkbox-inline label {padding-left: 8px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;}
+126
View File
@@ -110,8 +110,134 @@ function changeParentChecked($item, moduleName, packageID)
}
}
/**
* Init comp recomend-tree.
*
* @param array data
* @access public
* @return void
*/
function initRecomendTree(data)
{
$(".menuTree.depend").tree(
{
data: data,
initialState: 'active',
itemCreator: function($li, item)
{
$li.append('<a class="priv-item" data-has-children="' + (item.children ? !!item.children.length : false) + '" href="#" title="' + item.title + '">' + item.title + (item.children ? '' : '<i class="icon icon-close hidden" data-type="depend" data-privid=' + item.privID + ' data-relationpriv=' + item.relationPriv + '></i>') + '</a>');
if(item.active) $li.addClass('active open in');
}
});
}
/**
* Init comp depend-tree.
*
* @param array data
* @access public
* @return void
*/
function initDependTree(data)
{
$(".menuTree.recommend").tree(
{
data: data,
initialState: 'active',
itemCreator: function($li, item)
{
$li.append('<a class="priv-item" data-has-children="' + (item.children ? !!item.children.length : false) + '" href="#" title="' + item.title + '">' + item.title + (item.children ? '' : '<i class="icon icon-close hidden" data-type="recommend" data-privid=' + item.privID + ' data-relationpriv=' + item.relationPriv + '></i>') + '</a>');
if(item.active) $li.addClass('active open in');
}
});
}
/**
* update comp tree after click checkbox-label.
*
* @param obj objTree
* @access public
* @return void
*/
function updatePrivTree(objTree)
{
$(".menuTree.depend").data('zui.tree').reload(objTree.dependData || [] );
if(objTree.dependData && objTree.dependData.length)
{
$(".menuTree.depend + .empty-tip").addClass('hidden');
var privCount = 0;
$.each(objTree.dependData, function(index, item){if(item.children) privCount += item.children.length;});
$(".menuTree.depend").closest('.priv-panel').find('.panel-title .priv-count').html('(' + privCount + ')');
}
else
{
$(".menuTree.depend + .empty-tip").removeClass('hidden');
$(".menuTree.depend").closest('.priv-panel').find('.panel-title .priv-count').html('');
}
$(".menuTree.recommend").data('zui.tree').reload(objTree.recommendData || []);
if(objTree.recommendData && objTree.recommendData.length)
{
$(".menuTree.recommend + .empty-tip").addClass('hidden');
var privCount = 0;
$.each(objTree.recommendData, function(index, item){if(item.children) privCount += item.children.length;});
$(".menuTree.recommend").closest('.priv-panel').find('.panel-title .priv-count').html('(' + privCount + ')');
}
else
{
$(".menuTree.recommend + .empty-tip").removeClass('hidden');
$(".menuTree.recommend").closest('.priv-panel').find('.panel-title .priv-count').html('');
}
if(!canDeleteRelation) $('.side a.priv-item .icon-close').remove();
}
/**
* Get relation side.
*
* @param int $privID
* @access public
* @return void
*/
function getSideRelation(privID)
{
$.get(createLink('group', 'ajaxGetPrivRelations', "privID=" + privID), function(data)
{
var objTree = {};
if(data)
{
var relatedPriv = JSON.parse(data);
objTree.dependData = relatedPriv.depend;
objTree.recommendData = relatedPriv.recommend;
}
updatePrivTree(objTree);
})
}
/**
* Update depend and recommend privs.
*
* @param e $e
* @access public
* @return void
*/
function updateRelations(e)
{
if($('.bg-primary-pale').length) $('.bg-primary-pale').removeClass('bg-primary-pale');
$('#privListTable').length > 0 ? $(e.target).closest('tr').addClass('bg-primary-pale') : $(e.target).addClass('bg-primary-pale');
var selectedID = $('#privListTable').length == 0 ? $(e.target).siblings('input:checkbox').data('id') : $(e.target).closest('tr').attr('data-id');
$('.side a#addDependent').attr('href', createLink('group', 'addRelation', "privIdList=" + selectedID + '&type=depend')).removeAttr('disabled');
$('.side a#addRecommendation').attr('href', createLink('group', 'addRelation', "privIdList=" + selectedID + '&type=recommend')).removeAttr('disabled');
if(!$('.side a#addDependent').hasClass('modaled')) $('.side a#addDependent,.side a#addRecommendation').modal().addClass('modaled');
getSideRelation(selectedID);
}
$(function()
{
initRecomendTree([]);
initDependTree([]);
$('#privList > tbody > tr > th .check-all').change(function()
{
var id = $(this).find('input[type=checkbox]').attr('id');
+117 -80
View File
@@ -16,7 +16,7 @@
<a href='javascript:;' class='btn btn-link btn-active-text'><span class='text'><?php echo $group->name;?></span></a>
</div>
</div>
<div id='mainContent' class='main-content'>
<div id='mainContent' class='main main-content'>
<form class="load-indicator main-form form-ajax" id="managePrivForm" method="post">
<table class='table table-hover table-striped table-bordered'>
<thead>
@@ -76,88 +76,125 @@
</div>
</div>
</div>
<div id='mainContent' class='main-content'>
<form class="load-indicator main-form form-ajax" id="managePrivForm" method="post" target='hiddenwin'>
<table class='table table-hover table-striped table-bordered' id='privList'>
<thead>
<tr class='text-center'>
<th class='module'><?php echo $lang->group->module;?></th>
<th class='package'><?php echo '权限包';?></th>
<th class='method' colspan='2'><?php echo $lang->group->method;?></th>
</tr>
</thead>
<tbody>
<?php foreach($privList as $moduleName => $packages):?>
<?php if(!count((array)$packages)) continue;?>
<?php
$moduleActions = !empty($lang->resource->{$moduleName}) ? $lang->resource->{$moduleName} : null;
/* Check method in select version. */
if($version)
{
$hasMethod = false;
foreach($privMethods as $module => $methods)
{
foreach($methods as $method)
{
if(strpos($changelogs, ",$module-$method,") !== false)
{
$hasMethod = true;
break;
}
if(!$hasMethod) continue;
}
}
}
$i = 1;
$modulePrivs = count($privList[$moduleName], 1) - count($selectPrivs[$moduleName], 1);
$moduleSelect = array_sum($selectPrivs[$moduleName]);
?>
<?php foreach($packages as $packageID => $privs):?>
<tr class='<?php echo cycle('even, bg-gray');?>'>
<?php if($i == 1):?>
<th class='text-middle text-left module' rowspan="<?php echo $i == 1 ? count($packages) : 1;?>" data-module='<?php echo $moduleName;?>' all-privs='<?php echo $modulePrivs;?>' select-privs='<?php echo $moduleSelect;?>'>
<div class="checkbox-primary checkbox-inline checkbox-left check-all">
<input type='checkbox' id='allChecker<?php echo $moduleName;?>' value='1' <?php if(!empty($moduleSelect) and $modulePrivs == $moduleSelect) echo 'checked';?>>
<label class='text-left <?php if(!empty($moduleSelect) and $modulePrivs != $moduleSelect) echo 'checkbox-indeterminate-block';?>' for='allChecker<?php echo $moduleName;?>'><?php echo $lang->$moduleName->common;?></label>
</div>
</th>
<?php endif;?>
<div id='mainContent'>
<div class='main main-content'>
<form class="load-indicator main-form form-ajax" id="managePrivForm" method="post" target='hiddenwin'>
<table class='table table-hover table-striped table-bordered' id='privList'>
<thead>
<tr class='text-center'>
<th class='module'><?php echo $lang->group->module;?></th>
<th class='package'><?php echo '权限包';?></th>
<th class='method' colspan='2'><?php echo $lang->group->method;?></th>
</tr>
</thead>
<tbody>
<?php foreach($privList as $moduleName => $packages):?>
<?php if(!count((array)$packages)) continue;?>
<?php
$packagePrivs = count($privs);
$packageSelect = $selectPrivs[$moduleName][$packageID];
$moduleActions = !empty($lang->resource->{$moduleName}) ? $lang->resource->{$moduleName} : null;
/* Check method in select version. */
if($version)
{
$hasMethod = false;
foreach($privMethods as $module => $methods)
{
foreach($methods as $method)
{
if(strpos($changelogs, ",$module-$method,") !== false)
{
$hasMethod = true;
break;
}
if(!$hasMethod) continue;
}
}
}
$i = 1;
$unassigned = (!empty($moduleActions) and !empty($privMethods[$moduleName])) ? array_diff(array_keys(get_object_vars($moduleActions)), $privMethods[$moduleName]) : array();
$modulePrivs = count($privList[$moduleName], 1) - count($selectPrivs[$moduleName], 1) + count($unassigned);
$moduleSelect = array_sum($selectPrivs[$moduleName]);
?>
<th class='<?php echo $i == 1 ? 'td-sm' : 'td-md';?> text-middle text-left package' data-module='<?php echo $moduleName;?>' data-package='<?php echo $packageID;?>' all-privs='<?php echo $packagePrivs;?>' select-privs='<?php echo $packageSelect;?>'>
<div class="checkbox-primary checkbox-inline checkbox-left check-all">
<input type='checkbox' id='allCheckerModule<?php echo $moduleName;?>Package<?php echo $packageID;?>' value='1' <?php if($packagePrivs == $packageSelect) echo 'checked';?>>
<label class='text-left <?php if(!empty($packageSelect) and $packagePrivs != $packageSelect) echo 'checkbox-indeterminate-block';?>' for='allCheckerPackage<?php echo $packageID;?>'><?php echo zget($privPackages, $packageID, $lang->group->unassigned);?></label>
</div>
</th>
<?php if(isset($lang->$moduleName->menus)):?>
<td class='menus'>
<?php echo html::checkbox("actions[$moduleName]", array('browse' => $lang->$moduleName->browse), isset($groupPrivs[$moduleName]) ? $groupPrivs[$moduleName] : '');?>
<a href='javascript:;'><i class='icon icon-plus'></i></a>
<?php echo html::checkbox("actions[$moduleName]", $lang->$moduleName->menus, isset($groupPrivs[$moduleName]) ? $groupPrivs[$moduleName] : '');?>
</td>
<?php endif;?>
<td id='<?php echo $moduleName;?>' class='pv-10px' colspan='<?php echo !empty($lang->$moduleName->menus) ? 1 : 2?>'>
<?php foreach($privs as $privID => $priv):?>
<div class="group-item" data-module='<?php echo $moduleName;?>' data-package='<?php echo $packageID;?>'>
<div class="checkbox-primary">
<?php echo html::checkbox("actions[$priv->module]", array($priv->method => $priv->name), isset($groupPrivs[$priv->module][$priv->method]) ? $priv->method : '', "title='{$priv->name}' id='actions[$priv->module]$priv->method' data-id='$privID'");?>
<?php foreach($packages as $packageID => $privs):?>
<tr class='<?php echo cycle('even, bg-gray');?>'>
<?php if($i == 1):?>
<th class='text-middle text-left module' rowspan="<?php echo $i == 1 ? count($packages) : 1;?>" data-module='<?php echo $moduleName;?>' all-privs='<?php echo $modulePrivs;?>' select-privs='<?php echo $moduleSelect;?>'>
<div class="checkbox-primary checkbox-inline checkbox-left check-all">
<input type='checkbox' id='allChecker<?php echo $moduleName;?>' value='1' <?php if(!empty($moduleSelect) and $modulePrivs == $moduleSelect) echo 'checked';?>>
<label class='text-left <?php if(!empty($moduleSelect) and $modulePrivs != $moduleSelect) echo 'checkbox-indeterminate-block';?>' for='allChecker<?php echo $moduleName;?>'><?php echo $lang->$moduleName->common;?></label>
</div>
</div>
<?php endforeach;?>
</td>
</tr>
<?php $i ++;?>
<?php endforeach;?>
<?php endforeach;?>
</tbody>
</table>
</form>
</th>
<?php endif;?>
<?php
$packagePrivs = count($privs);
$packageSelect = $selectPrivs[$moduleName][$packageID] + ($packageID == 0 ? count($unassigned) : 0);
?>
<th class='<?php echo $i == 1 ? 'td-sm' : 'td-md';?> text-middle text-left package' data-module='<?php echo $moduleName;?>' data-package='<?php echo $packageID;?>' all-privs='<?php echo $packagePrivs;?>' select-privs='<?php echo $packageSelect;?>'>
<div class="checkbox-primary checkbox-inline checkbox-left check-all">
<input type='checkbox' id='allCheckerModule<?php echo $moduleName;?>Package<?php echo $packageID;?>' value='1' <?php if($packagePrivs == $packageSelect) echo 'checked';?>>
<label class='text-left <?php if(!empty($packageSelect) and $packagePrivs != $packageSelect) echo 'checkbox-indeterminate-block';?>' for='allCheckerPackage<?php echo $packageID;?>'><?php echo zget($privPackages, $packageID, $lang->group->unassigned);?></label>
</div>
</th>
<?php if(isset($lang->$moduleName->menus)):?>
<td class='menus'>
<?php echo html::checkbox("actions[$moduleName]", array('browse' => $lang->$moduleName->browse), isset($groupPrivs[$moduleName]) ? $groupPrivs[$moduleName] : '');?>
<a href='javascript:;'><i class='icon icon-plus'></i></a>
<?php echo html::checkbox("actions[$moduleName]", $lang->$moduleName->menus, isset($groupPrivs[$moduleName]) ? $groupPrivs[$moduleName] : '');?>
</td>
<?php endif;?>
<td id='<?php echo $moduleName;?>' class='pv-10px' colspan='<?php echo !empty($lang->$moduleName->menus) ? 1 : 2?>'>
<?php foreach($privs as $privID => $priv):?>
<div class="group-item" data-module='<?php echo $moduleName;?>' data-package='<?php echo $packageID;?>'>
<div class="checkbox-primary">
<?php echo html::checkbox("actions[$priv->module]", array($priv->method => $priv->name), isset($groupPrivs[$priv->module][$priv->method]) ? $priv->method : '', "title='{$priv->name}' id='actions[$priv->module]$priv->method' data-id='$privID'");?>
</div>
</div>
<?php endforeach;?>
<?php if($packageID == 0):?>
<?php foreach($moduleActions as $action => $actionLabel):?>
<?php if(array_search($action, $unassigned) === false) continue;?>
<div class="group-item" data-module='<?php echo $moduleName;?>' data-package='<?php echo $packageID;?>'>
<div class="checkbox-primary">
<?php echo html::checkbox("actions[{$moduleName}]", array($action => $lang->$moduleName->$actionLabel), isset($groupPrivs[$moduleName][$action]) ? $action : '', "title='{$lang->$moduleName->$actionLabel}'", 'inline');?>
</div>
</div>
<?php endforeach;?>
<?php endif;?>
</td>
</tr>
<?php $i ++;?>
<?php endforeach;?>
<?php endforeach;?>
</tbody>
</table>
</form>
</div>
<div class="side">
<div class="priv-panel">
<div class="panel-title">
<?php echo $lang->group->dependentPrivs?>
</div>
<div class="panel-content">
<div class="menuTree depend menu-active-primary menu-hover-primary"></div>
<div class="empty-tip flex-center">
<p><span class="text-muted"><?php echo $lang->noData;?></span></p>
</div>
</div>
</div>
<div class="priv-panel mt-m">
<div class="panel-title">
<?php echo $lang->group->recommendPrivs?>
</div>
<div class="panel-content">
<div class="menuTree recommend menu-active-primary menu-hover-primary"></div>
<div class="empty-tip flex-center">
<p><span class="text-muted"><?php echo $lang->noData;?></span></p>
</div>
</div>
</div>
</div>
</div>
<?php endif;?>
<?php js::set('groupID', $groupID);?>