CRM项目之权限分配6

权限分配思路

在一个页面分为三个面板(左中右三块),分别展示所有用户,所有角色,所有权限。
用户的展示:将所有用户展示,点击用户显示所有角色界面,为该用户分配角色其分配角色。
角色的展示:展示被点击用户所拥有的角色,选中角色对应的checkbox框来为该用户分配权限。
权限的展示:有三层,一级菜单->可做二级菜单的权限->不可做菜单的权限,可做三层循环来展示,为其构造用于循环展示的格式的数据

menu_permission_list = [
        # 一级菜单
        {
            'id': 1,
            'title': '业务管理',
            'children' : [
                # 二级菜单
                {
                    'id': 11,
                    'title': '账单列表',
                    'children': [
                        # 不可做菜单的权限
                        {
                            'id': 3,
                            'title': '添加账单'
                        }
                    ]
                }
            ]
        }
    ]

权限分配页面显示

路由

url(r'^distribute/permissions/', menu.distribute_permissions, name='distribute_permissions')

试图函数,构造权限信息展示的结构

def distribute_permissions(request):
    all_users_list = models.UserInfo.objects.all()
    all_roles_list = models.Role.objects.all()
    # 所有的一级菜单
    all_menu_list = models.Menu.objects.values('id', 'title')
    # 所有二级菜单
    all_second_menu_list = models.Permission.objects.filter(menu__isnull=False).values('id', 'title', 'menu_id')
    # 所有三级菜单
    all_permission_list = models.Permission.objects.filter(menu__isnull=True).values('id', 'title', 'pid_id')

    # 使用字典来同步更新列表中的值,key对应的value和列表中的元素指向的是同一块内存地址。
    all_menu_dict = {}
    all_second_menu_dict = {}
    for item in all_menu_list:
        item['children'] = []
        all_menu_dict[item['id']] = item

    # 二级菜单挂靠到一级菜单下
    for row in all_second_menu_list:
        row['children'] = []
        menu_id = row.get('menu_id')
        all_second_menu_dict[row['id']] = row
        all_menu_dict[menu_id]['children'].append(row)

    # 不能做菜单的权限挂靠到二级菜单
    for row in all_permission_list:
        pid_id = row.get('pid_id')
        if pid_id:
            all_second_menu_dict[pid_id]['children'].append(row)


    return render(
        request,
        'rbac/distribute_permissions.html',
        {
            'user_list': all_users_list,
            'role_list': all_roles_list,
            'menu_list': all_menu_list
        },
    )

模板distribute_permissions.html

{% extends 'layout.html' %}
{% load rbac %}
{% block css %}
	<style>
		tr.active{
			border-left: 3px solid #fdc00f
		}

		.permission-area tr.root{
			background-color: #f1f7fd;
		}
		.permission-area tr.root td i{
			margin: 3px;
		}
		.permission-area .node{

		}
		.permission-area .node input[type='checkbox']{
			margin: 0 5px;
		}
		.permission-area .node .parent{
			padding: 5px 0;
		}
		.permission-area .node label{
			font-weight: normal;
			margi-bottom: 0
			font-size: 12px;
		}
		.permission-area .node .children{
			padding: 0 0 0 25px;
		}
		.permission-area .node .children .child{
			display: inline-block;
			margin: 2px 5px;
		}
		.select-help{
			float: right;
		}
		.select-help .label{
			font-weight: normal;
			cursor: pointer;
		}
		.select-help .check-all{
			float: right;
			display: inline-block;
			margin-right: 8px;
		}

	</style>
{% endblock %}

{% block content %}
    <div class="luffy-container">
		<div class="col-md-3">
			<div class="panel panel-info">
				<!-- Default panel contents -->
				<div class="panel-heading">
					<i class="fa fa-book" aria-hidden="true"></i>用户信息
				</div>

				<!-- Table -->
				<ul>
					{% for row in user_list %}
                    	<li><a href="?uid={{ row.id }}">{{ row.name }}</a></li>
					{% endfor %}
                </ul>
			</div>
		</div>
		<div class="col-md-4">
			<div class="panel panel-info">
				<!-- Default panel contents -->
				<div class="panel-heading">
					<i class="fa fa-book" aria-hidden="true"></i>角色信息
				</div>
				<div class="panel-body">
					提示:选中用户才能为其分配角色
				</div>
				<table class="table">
					<thead>
						<tr>
							<th>角色</th>
							<th>选项</th>
						</tr>
					</thead>
					<tbody>
						{% for row in role_list %}
							<tr>
								<td>{{ row.title }}</td>
								<td><input type="checkbox" name="roles" id="" value="{{ row.id }}"></td>
							</tr>
						{% endfor %}
					</tbody>
				</table>
			</div>
		</div>
		<div class="col-md-5 permission-area">
			<div class="panel panel-info">
				<!-- Default panel contents -->
				<div class="panel-heading">
					<i class="fa fa-book" aria-hidden="true"></i>权限分配
				</div>
				<div class="panel-body">
					提示:选中角色才能为其分配权限
				</div>
				<table class="table">
					<tbody>
						{% for item in menu_list  %}
							<tr class="root">
								<td>
									<i class="fa fa-caret-down" aria-hidden=""></i>
									{{ item.title }}
									<div class="select-help">
										<div class="check-all">
											<label for="check-all_{{ item.id }}">全选</label>
											<input type="checkbox" name="" id="check-all_{{ item.id }}">
										</div>
									</div>
								</td>
							</tr>
							<tr class="node">
								<td>
									{% for node in item.children %}
										<div class="parent">
											<input type="checkbox" name="permissions" id="permission_{{ node.id }}"
												value="{{ node.id }}">
											<label for="permission_{{ node.id }}">{{ node.title }} (菜单)</label>
										</div>
										<div class="children">
											{% for child in node.children %}
												<div class="child">
													<input type="checkbox" name="permissions" id="permission_{{ child.id }}"
													value="{{ child.id }}">
													<label for="permission_{{ child.id }}">{{ child.title }}</label>
												</div>
											{% endfor %}
										</div>
									{% endfor %}
								</td>
							</tr>
						{% endfor %}
					</tbody>
				</table>
			</div>
		</div>

		
    </div>

{% endblock %}

效果
CRM项目之权限分配6

点击选中的用户展示该用户拥有的角色

根据用户id拿到该用户下的所有角色,将所有角色的id已{'id值':None}的形式存储。

# 筛选出当前用户拥有的角色
    if user_id:
        user_has_roles = user_obj.roles.all()
    else:
        user_has_roles = []
    user_has_roles_dict = {item.id: None for item in user_has_roles}

在前端展示checkbox时进行判断,如果其角色id在user_has_roles_dict中,说明用户已拥有该角色,将其设置为checked,显示为选中。

<tbody>
	{% for row in role_list %}
		<tr>
			<td>{{ row.title }}</td>
			<td><input type="checkbox" name="roles" value="{{ row.id }}" {% if row.id in user_has_roles_dict %}checked{% endif %}></td>
		</tr>
	{% endfor %}
</tbody>

点击选中的用户展示该用户拥有的所有权限

根据用户对象,拿到该用户拥有的所有权限,将权限的id以{‘权限id值’:None}的形式存储,注意跨表,用户表->角色表->拿到角色下的所有权限,角色和权限是多对多关系,获取的到权限可能重复,要做去重。

    # 筛选出当前用户拥有的权限
    if user_id:
        user_has_permissions = user_obj.roles.filter(permissions__id__isnull=False).values('id', 'permissions').distinct()
    else:
        user_has_permissions = []
    user_has_permissions_dict = {item['permissions']: None for item in user_has_permissions}

在前端展示checkbox时进行判断,如果其角色id在user_has_permissions_dict 中,说明用户已拥有该角色,将其设置为checked,显示为选中。

<tr class="node">
	<td>
		{% for node in item.children %}
			<div class="parent">
				<input type="checkbox" name="permissions" id="permission_{{ node.id }}"
					value="{{ node.id }}"{% if node.id in user_has_permissions_dict %}checked{% endif %}>
				<label for="permission_{{ node.id }}">{{ node.title }} (菜单)</label>
			</div>
			<div class="children">
				{% for child in node.children %}
					<div class="child">
						<input type="checkbox" name="permissions" id="permission_{{ child.id }}"
						value="{{ child.id }}" {% if child.id in user_has_permissions_dict %}checked{% endif %}>
						<label for="permission_{{ child.id }}">{{ child.title }}</label>
					</div>
				{% endfor %}
			</div>
		{% endfor %}
	</td>
</tr>

效果:
CRM项目之权限分配6

点击角色显示角色下的已分配权限信息

点击角色显示该角色选中的样式:

.role-area tr td a{
	display:block;
}
.role-area tr.active{
	background-color:#f1f7fd;
	border-left: 3px solid #fdc00f;
}

有两种情况进行处理:

  1. 在点击了用户后,再点击角色
  2. 直接点击角色
    给用户分配权限,是通过角色间接的分配权限,直接点击角色,显示角色的权限分配
    CRM项目之权限分配6
    点击用户后,再点击角色,会显示该角色下的权限,给该角色权限进行分配,但是用户分配角色的功能应该不受影响,依旧可以分配角色给用户。点击角色信息的保存,给用户分配角色;点击权限分配的保存,给角色分配权限。
    CRM项目之权限分配6
    代码实现:
    视图函数
def distribute_permissions(request):
    user_id = request.GET.get('uid')
    role_id = request.GET.get('rid')
    user_obj = models.UserInfo.objects.filter(pk=user_id).first()
    role_obj = models.Role.objects.filter(pk=role_id).first()
    if not user_obj:
        user_id = None
    if not role_obj:
        role_id = None

    # 筛选出当前用户拥有的角色
    if user_id:
        user_has_roles = user_obj.roles.all()
    else:
        user_has_roles = []
    user_has_roles_dict = {item.id: None for item in user_has_roles}
    # 筛选出当前用户拥有的权限
    # 如果选中了角色,优先显示选中角色所有的权限;如果没有选中角色,才显示用户所拥有的权限
    if role_obj:  # 选择了角色
        user_has_permissions = role_obj.permissions.values('id')
        user_has_permissions_dict = {item['id']: None for item in user_has_permissions}
    elif user_obj:  # 选择了用户,没有选择角色
        user_has_permissions = user_obj.roles.filter(permissions__id__isnull=False).values('id',
                                                                                           'permissions').distinct()
        user_has_permissions_dict = {item['permissions']: None for item in user_has_permissions}
    else:
        user_has_permissions_dict = {}

    all_users_list = models.UserInfo.objects.all()
    all_roles_list = models.Role.objects.all()
    # 所有的一级菜单
    all_menu_list = models.Menu.objects.values('id', 'title')
    # 所有二级菜单
    all_second_menu_list = models.Permission.objects.filter(menu__isnull=False).values('id', 'title', 'menu_id')
    # 所有三级菜单
    all_permission_list = models.Permission.objects.filter(menu__isnull=True).values('id', 'title', 'pid_id')

    # 使用字典来同步更新列表中的值,key对应的value和列表中的元素指向的是同一块内存地址。
    all_menu_dict = {}
    all_second_menu_dict = {}
    for item in all_menu_list:
        item['children'] = []
        all_menu_dict[item['id']] = item

    # 二级菜单挂靠到一级菜单下
    for row in all_second_menu_list:
        row['children'] = []
        menu_id = row.get('menu_id')
        all_second_menu_dict[row['id']] = row
        all_menu_dict[menu_id]['children'].append(row)

    # 不能做菜单的权限挂靠到二级菜单
    for row in all_permission_list:
        pid_id = row.get('pid_id')
        if pid_id:
            all_second_menu_dict[pid_id]['children'].append(row)


    return render(
        request,
        'rbac/distribute_permissions.html',
        {
            'user_list': all_users_list,
            'role_list': all_roles_list,
            'menu_list': all_menu_list,
            'user_id': user_id,
            'role_id': role_id,
            'user_has_roles_dict': user_has_roles_dict,
            'user_has_permissions_dict': user_has_permissions_dict,
        },
    )

模板

{% extends 'layout.html' %}
{% load rbac %}
{% block css %}
	<style>
		.user-area ul{
			padding-left: 20px;
		}
		.user-area li{
			cursor: pointer;
			padding: 2px 0;
		}
		.user-area li a{
			display:block;
		}
		.user-area li.active{
			font-weight: bold;
			color:red;
		}
		.user-area li.active a{
			color:red
		}

		.role-area tr td a{
			display:block;
		}
		.role-area tr.active{
			background-color:#f1f7fd;
			border-left: 3px solid #fdc00f;
		}

		.permission-area tr.root{
			background-color: #f1f7fd;
		}
		.permission-area tr.root td i{
			margin: 3px;
		}
		.permission-area .node{

		}
		.permission-area .node input[type='checkbox']{
			margin: 0 5px;
		}
		.permission-area .node .parent{
			padding: 5px 0;
		}
		.permission-area .node label{
			font-weight: normal;
			margi-bottom: 0
			font-size: 12px;
		}
		.permission-area .node .children{
			padding: 0 0 0 25px;
		}
		.permission-area .node .children .child{
			display: inline-block;
			margin: 2px 5px;
		}
		.select-help{
			float: right;
		}
		.select-help .label{
			font-weight: normal;
			cursor: pointer;
		}
		.select-help .check-all{
			float: right;
			display: inline-block;
			margin-right: 8px;
		}

	</style>
{% endblock %}

{% block content %}
    <div class="luffy-container">
		<div class="col-md-3 user-area">
			<div class="panel panel-info">
				<!-- Default panel contents -->
				<div class="panel-heading">
					<i class="fa fa-book" aria-hidden="true"></i>用户信息
				</div>

				<div class="panel-body">
					<ul>
						{% for row in user_list %}
							<li class="{% if user_id == row.id|safe %} active {% endif %}"><a href="?uid={{ row.id }}">{{ row.name }}</a></li>
						{% endfor %}
					</ul>
				</div>
			</div>
		</div>
		<div class="col-md-4 role-area">
			<div class="panel panel-info">
				<!-- Default panel contents -->
				<div class="panel-heading">
					<i class="fa fa-book" aria-hidden="true"></i>角色信息
					{% if user_id %}
						<a href="#" class="right btn btn-primary btx-xs"
						   style="margin: -3px; padding: 2px 8px;">
							<i class="fa fa-save" aria-hidden="true"></i>
							保存
						</a>
					{% endif %}
				</div>
				<div class="panel-body">
					提示:选中用户才能为其分配角色
				</div>
				<table class="table">
					<thead>
						<tr>
							<th>角色</th>
							<th>选项</th>
						</tr>
					</thead>
					<tbody>
						{% for row in role_list %}
							<tr class="{% if row.id|safe == role_id %}active{% endif %}">

								<td>
									{% if user_id %}
										<a href="?uid={{ user_id }}&rid={{ row.id }}">{{ row.title }}</a>
									{% else %}
										<a href="?rid={{ row.id }}">{{ row.title }}</a>
									{% endif %}
								</td>
								<td><input type="checkbox" name="roles" value="{{ row.id }}" {% if row.id in user_has_roles_dict %}checked{% endif %}></td>
							</tr>
						{% endfor %}
					</tbody>
				</table>
			</div>
		</div>
		<div class="col-md-5 permission-area">
			<div class="panel panel-info">
				<!-- Default panel contents -->
				<div class="panel-heading">
					<i class="fa fa-book" aria-hidden="true"></i>权限分配
					{% if role_id %}
						<a href="#" class="right btn btn-primary btx-xs"
						   style="margin: -3px; padding: 2px 8px;">
							<i class="fa fa-save" aria-hidden="true"></i>
							保存
						</a>
					{% endif %}
				</div>
				<div class="panel-body">
					提示:选中角色才能为其分配权限
				</div>
				<table class="table">
					<tbody>
						{% for item in menu_list  %}
							<tr class="root">
								<td>
									<i class="fa fa-caret-down" aria-hidden=""></i>
									{{ item.title }}
									<div class="select-help">
										<div class="check-all">
											<label for="check-all_{{ item.id }}">全选</label>
											<input type="checkbox" name="" id="check-all_{{ item.id }}">
										</div>
									</div>
								</td>
							</tr>
							<tr class="node">
								<td>
									{% for node in item.children %}
										<div class="parent">
											<input type="checkbox" name="permissions" id="permission_{{ node.id }}"
												value="{{ node.id }}"{% if node.id in user_has_permissions_dict %}checked{% endif %}>
											<label for="permission_{{ node.id }}">{{ node.title }} (菜单)</label>
										</div>
										<div class="children">
											{% for child in node.children %}
												<div class="child">
													<input type="checkbox" name="permissions" id="permission_{{ child.id }}"
													value="{{ child.id }}" {% if child.id in user_has_permissions_dict %}checked{% endif %}>
													<label for="permission_{{ child.id }}">{{ child.title }}</label>
												</div>
											{% endfor %}
										</div>
									{% endfor %}
								</td>
							</tr>
						{% endfor %}
					</tbody>
				</table>
			</div>
		</div>

		
    </div>

{% endblock %}

权限分配页面保存按钮

有两个保存按钮,一个是角色分配的保存按钮,一个是权限分配的保存按钮。也就是说点击会有两个form表单提交到同一url到后台,后台需要区分不同的表单进行处理,区分的方式是在各自的form下写一个intput标签<input type="text" name="type" value="permission" hidden> <input type="text" name="type" value="permission" hidden>后台获取提交的input的标签内容来区分不同的表单

if request.method == "POST" and request.POST.get('type') == "role":
    print('角色')

if request.method == "POST" and request.POST.get('type') == "permission":
    print('权限')

后端进行保存:

    if request.method == "POST" and request.POST.get('type') == "role":
        role_id_list = request.POST.getlist('roles')
        if not user_obj:
            return HttpResponse('请选择用户,再分配角色')
        user_obj.roles.set(role_id_list)

    if request.method == "POST" and request.POST.get('type') == "permission":
        permission_id_list = request.POST.getlist('permissions')
        if not role_obj:
            return HttpResponse('请选择角色,再分配权限')
        role_obj.permissions.set(permission_id_list)

权限分配之全选

使用js来实现,再点击权限时,给每个input checkbox标签加上checked就可以

{% block js %}
<script type="text/javascript">
	$(function(){
		$('.check-all input:checkbox').change(function(){
			$(this).parents('.root').next().find(':checkbox').prop('checked', $(this).prop('checked'))
		})
	})
</script>
{% endblock %}
上一篇:three swords


下一篇:CRM客户管理系统解决金融企业客户管理难题