二级菜单优化功能

Posted crazysheldon1

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二级菜单优化功能相关的知识,希望对你有一定的参考价值。

二级菜单的功能优化---渐入佳境

功能1:点击其中之一的一级菜单展示其二级菜单,同时其他一级菜单的二级菜单都处于闭合状态

思路:使用jsDOM操作进行实现

html示例代码
<div class="multi-menu">
    {% for menu in menu_list %}
        <div class="item">
            <div class="title"><i class="fa {{ menu.icon }}"></i>
                {{ menu.name }}</div>
            <div class="body">
                {% for child in menu.children %}
                    <a href="{{ child.url }}">{{ child.title }}</a>
                {% endfor %}
                
            </div>
        </div>
    {% endfor %}
</div>

js代码实现

$(‘.item .title‘).click(function () {
    $(this).next().removeClass(‘hide‘).parent().siblings().find(‘.body‘).addClass(‘hide‘)
})

//1.先命中一级菜单title,触发点击事件
//2.保证自己没有被隐藏
//3.找到其他body使其隐藏,通过自己先找到父级parent,再找到所有的兄弟siblings的儿子,也就是body,命中后添加hide属性

//如此便实现了这个只显示当前菜单下的二级菜单功能

功能2:访问当前页面,默认选中对应页面展示菜单

思路:在访问的二级菜单url对应a标签中添加 class=‘active‘

1.django中 templatetags文件下使用inclusion_tag进行自定义模板

#从二级菜单的数据结构中获取到需要使用的url,title进行模板渲染
"""
{
    1: {
        ‘name‘: ‘信息管理‘,
        ‘icon‘: ‘fa-email‘,
        ‘children‘: [{
            ‘title‘: ‘客户管理‘,
            ‘url‘: ‘/customer/list/‘
        }]
    },
}
"""
from django import template
import re
from permission import settings
register = template.Library()
#自定义模板
@register.inclusion_tag(menu.html)
def menu(request):
    menu_dic = request.session.get(settings.MENU_SESSION_KEY)
    url = request.path_info #获取访问的url

    #获取到url和title进行模板渲染
    for item in menu_dic.values(): #首先循环拿到item表示一级菜单id对应的所有内容

        for i in item[children]: #循环item[‘children‘] 要拿到i 表示二级菜单内的所有内容
            if re.match("^{}$".format(i[url]),url): #将获取到url与session中的url进行正则匹配
                i[class] = active #匹配成功后给二级菜单字典内添加一组键值对 class=‘active‘
                break
    return {menu_list:menu_dic.values()}

 

2.在对应的模板中直接渲染即可,参照功能1中的HTML代码

  <a class="{{ child.class }}" href="{{ child.url }}">{{ child.title }}</a>

根据上面的HTML代码来看,在class=body 下的a标签中添加class=‘active‘进行渲染即可.
***如此便实现了
访问某个页面,默认选中对应页面的展示菜单***

 

功能3访问某个页面,页面对应菜单的二级菜单展示,其他菜单的二级菜单默认关闭

思路:首先先隐藏所有的二级菜单,再根据访问的url展示对应的一级菜单下的二级菜单

#示例代码
from
django import template import re from luffy_permission import settings register = template.Library() #自定义模板 @register.inclusion_tag(menu.html) def menu(request): menu_dic = request.session.get(settings.MENU_SESSION_KEY) url = request.path_info for item in menu_dic.values(): item[class] = hide #将所有的二级菜单隐藏 for i in item[children]: if re.match("^{}$".format(i[url]),url): i[class] = active item[class] = ‘‘ #将匹配成功的二级菜单取消隐藏 break return {menu_list:menu_dic.values()}

 

<div class="multi-menu">
    {% for menu in menu_list %}
        <div class="item">
            <div class="title"><i class="fa {{ menu.icon }}"></i>
                {{ menu.name }}</div>
            <div class="body {{ menu.class }}">    
                {% for child in menu.children %}
                    <a class="{{ child.class }}" href="{{ child.url }}">{{ child.title }}</a>
                {% endfor %}
                
            </div>
        </div>
    {% endfor %}
</div>

注:先在body中添加class=‘hide‘属性,令所有的二级菜单隐藏,当访问的url页面匹配与session中的url匹配成功后在将 class=‘‘ 从而取消隐藏

 

功能4固定菜单栏展示顺序,因为数据结构是字典(无序的)

思路:将menu表结构改变,添加一个字段weight = model.IntegerField(default=1),导入有序字典(from collections import OrderedDict),根据数值大小进行排序即可

models.py
class
Menu(models.Model): """ 一级菜单 """ name = models.CharField(max_length=30,verbose_name=一级菜单名称) icon = models.CharField(max_length=56, verbose_name=图标, blank=True, null=True) weight = models.IntegerField(default=1) def __str__(self): return self.name #添加一个字段weight

 

rbac.py
from django import template import re from permission import settings from collections import OrderedDict register = template.Library() #自定义模板 @register.inclusion_tag(menu.html) def menu(request): menu_dic = request.session.get(settings.MENU_SESSION_KEY)
   url = request.path_info order_dic
= OrderedDict() #实例化一个有序字典 for key in sorted(menu_dic,key=lambda n:menu_dic[n][weight],reverse=True): order_dic[key] = item = menu_dic[key] #将根据weight字段排序后的menu_dic 赋值给order_dic item[class] = hide for i in item[children]: if re.match("^{}$".format(i[url]),url): i[class] = active item[class] = ‘‘ break return {menu_list:order_dic.values()} #再返回有序字典在模板上顺序渲染

 

功能5:非菜单权限归属问题 (二级菜单内各种时操作 默认选中并处于显示对应二级菜单)

思路:二级菜单下需要有操作的层级关系,也就是你伪三级菜单 ,更改表结构也就是 权限表(Permission)

 步骤1:表结构设计 models.py

技术图片

 

#参照上图所示
class
Permission(models.Model): """ 权限表 menu_id 有的话 表示当前的权限是二级菜单 父权限 没有 是一个普通权限 parent_id 有的话 表示当前就是子权限 没有的话就是一个父权限 """ url = models.CharField(max_length=255,verbose_name=地址) title = models.CharField(max_length=25,verbose_name=标题) menu = models.ForeignKey(Menu,blank=True,null=True) parent = models.ForeignKey(self) #自关联 获取到层级结构

 

 步骤2:查询和存放在session中的权限信息处理 service/permission.py

技术图片
 1 from django.conf import settings
 2 
 3 
 4 def init_permission(request,obj):
 5     # 先查到需要的权限信息,
 6 
 7     permission_query = obj.roles.all().filter(permissions__url__isnull=False).values(permissions__url,
 8                                                                                      permissions__title,
 9                                                                                      permissions__menu__name,
10                                                                                      permissions__menu__icon,
11                                                                                      permissions__menu__id,
12                                                                                      permissions__menu__weight,
13                                                                                      permissions__id,
14                                                                                      permissions__parent_id,
15                                                                                      ).distinct()
16     # 存放权限信息列表
17     permission_list = []
18     # 存放菜单信息的字典
19     menu_dic = {}
20     for item in permission_query:
21         # 将权限信息放到permission_list
22         permission_list.append({url: item[permissions__url],
23                                 pid: item[permissions__parent_id],
24                                 id: item[permissions__id] })
25 
26         #放入菜单信息
27         menu_id = item[permissions__menu__id]
28         if not menu_id:
29             continue
30         if menu_id not in menu_dic:
31             menu_dic[menu_id] = {
32                 name: item[permissions__menu__name],
33                 icon: item[permissions__menu__icon],
34                 weight: item[permissions__menu__weight],
35                 children: [{
36                     title: item[permissions__title],
37                     url: item[permissions__url],
38                     id: item[permissions__id],
39                 }]
40             }
41         else:
42             menu_dic[menu_id][children].append({
43                 title: item[permissions__title],
44                 url: item[permissions__url],
45                 id: item[permissions__id],
46             })
47 
48     request.session[settings.PERMISSION_SESSION_KEY] = permission_list
49     request.session[settings.MENU_SESSION_KEY] = menu_dic
权限信息查询和session中保存

 

步骤3.中间件权限校验,处理访问url归属问题 middlewares/rbac.py

技术图片
 1 from django.utils.deprecation import MiddlewareMixin
 2 import re
 3 from django.conf import settings
 4 from django.shortcuts import HttpResponse,redirect,reverse
 5 
 6 class RbacMiddleware(MiddlewareMixin):
 7 
 8     def process_request(self,request):
 9         #获取当前的url
10         url = request.path_info
11 
12         #白名单
13         for i in settings.WHITE_LIST:
14             if re.match(i,url):
15                 return
16 
17         #获取权限信息
18         permission_list = request.session.get(settings.PERMISSION_SESSION_KEY)
19         if not permission_list:
20             return redirect(reverse(login))
21         #权限校验
22 
23         for item in permission_list:
24             # i 里面有{url pid  id}
25             if re.match("^{}$".format(item[url]),url):
26                 #要显示的二级菜单的id
27                 pid = item.get(pid)
28                 id = item.get(id)
29                 #此步操作就是表示不管是pid还是id都是显示的二级菜单的id
30                 if pid:
31                     #当前访问的是子权限,找父权限显示
32                     request.current_menu_id = pid
33                 else:
34                     #当前访问的是父权限,也就是二级菜单,找自己显示
35                     request.current_menu_id = id
36                 return
37         return HttpResponse(您没有访问的权限)
中间件处理访问的权限url归属问题

 

步骤4.自定义模板中二级菜单id和session中存的匹配成功

技术图片
from django import template
import re
from luffy_permission import settings
from collections import OrderedDict

register = template.Library()
#自定义模板
@register.inclusion_tag(menu.html)
def menu(request):
    menu_dic = request.session.get(settings.MENU_SESSION_KEY)
    url = request.path_info  
    order_dic = OrderedDict()  
    for i in sorted(menu_dic,key=lambda n:menu_dic[n][weight],reverse=True):
        order_dic[i] = item = menu_dic[i] 
    # for item in order_dic.values(): 
        item[class] = hide  
        for i in item[children]: 
            if i[id] == request.current_menu_id:#session中的id和访问的二级菜单id匹配
                i[class] = active 
                item[class] = ‘‘ 
                break
    return {menu_list:order_dic.values()}
自定义模板

 

以上是关于二级菜单优化功能的主要内容,如果未能解决你的问题,请参考以下文章

PHP+ajax实现二级联动菜单功能

QT之二级菜单(二级菜单的箭头可以使用QSS设置图片)

关于css二级菜单显示, 看了一个例子, 鼠标放在一级菜单时候, 二级菜单就显示出来了

Jquery垂直下拉二级菜单

CSS3实现二级菜单

Python 三级菜单与优化(一层循环嵌套)