zoukankan      html  css  js  c++  java
  • 动态菜单之 点击非菜单权限, 默认选中子菜单,与展开

    这是一个添加用户的,界面。 这个功能不是一个菜单选项。 他在 用户管理-->客户列表 页面中的一个功能。
    但是当我点击的时候,  左侧的信息,全部收缩起来了。 我觉得应该时要展开这个一级标签,并且还要有 选中 客户列表的这样一个提示。
    so  又有了我问题, 想想解决办法:

    思路是这样子的:

      - 登录,做权限和菜单的初始化。
        - 获取菜单信息

    {
        1: {'title': '用户管理',
            'icon': 'fa-envira',
            'children': [{'id': 1, 'title': '客户列表', 'url': '/customer/list/'}]
            },
        2: {'title': '信息管理',
            'icon': 'fa-black-tie',
            'children': [{'id': 7, 'title': '账单列表', 'url': '/payment/list/'}]
            }
    }

        - 获取权限信息( 进行更改之后的数据结构 )

    [
        {'id': 1, 'url': '/customer/list/', 'paren_id': None},               # 客户列表: 可以作为子菜单的
        {'id': 2, 'url': '/customer/add/', 'paren_id': 1},                   # 添加客户: 不可
        {'id': 3,  'url': '/customer/edit/(?P<cid>\d+)/', 'paren_id': 1},   # 编辑客户: 不可 
        {'id': 4, 'url': '/customer/del/(?P<cid>\d+)/', 'paren_id': 1},
        {'id': 5, 'url': '/customer/import/', 'paren_id': 1},
        {'id': 6, 'url': '/customer/tpl/', 'paren_id': 1},
        {'id': 7, 'url': '/payment/list/', 'paren_id': None},                # 账单列表: 可以作为子菜单的
        {'id': 8, 'url': '/payment/add/', 'paren_id': 7},
        {'id': 9, 'url': '/payment/edit/(?P<pid>\d+)/', 'paren_id': 7},
        {'id': 10, 'url': '/payment/del/(?P<pid>\d+)/', 'paren_id': 7}
    ]
    

    (解释:我们在循环这个,权限信息列表的时候。 使用当前访问的url  和  列表字典中的 url 进行匹配。 如果他的 parent_id 为null。那么这个  'id': 1 就是需要显示被选中的子菜单。 如果他的 parent_id 不为null,那么这个 'paren_id': 1 关联的 "id":1 的这条权限,就是需要显示被选中的子菜单。   这个 id 或者 parent_id 是需要传给inclusion_tag进行使用的。)( 因为做了所属关系,所以这里 不管是 id 还是 parent_id 都是  子菜单的主键 id)

      - 再次进行访问。
        - 中间件中进行权限的校验(根据权限信息 进行校验)
          获取id 或 parent_id (应该呗选中的,可以做菜单的 权限id)。 然后传递给 inclusion_tag

      - 模板中使用 inclusion_tag 生成动态菜单 (根据菜单信息,进行动态生成)
        这里在做 显示被选中的菜单的时候, 就不能再只去判断,url 是否匹配。 而是要判断,于当前url 相匹配的,他的id,  与权限列表中id或parent_id 相等的那个。    权限子菜单,要被选中。

    1. 当点击某个不能成为权限的菜单时,指定一个可以成为菜单的权限。让其默认的选中以及展开。( so 我们需要,为这个权限做一个归属。)
    还是依然对,数据库进行 开刀:

    class Permission(models.Model):
        """
        权限表  一级菜单的表
        """
        title = models.CharField(verbose_name='标题', max_length=32)
        url = models.CharField(verbose_name='含正则的URL', max_length=128)
        menu = models.ForeignKey(verbose_name="所属菜单", to="Menu", null=True, blank=True, on_delete=models.CASCADE)
        parent_Permission = models.ForeignKey(verbose_name="关联权限", help_text="对于非菜单权限,需要确定当前权限归属于哪一个,父权限",
                  to="Permission", null=True, blank=True, on_delete=models.CASCADE,related_name="parents")
    
        def __str__(self):
            return self.title
    Permission 表,再次修改,添加自关联字段

    so 添加完成后,的这个表。 应该是这个样子的。

    2. 对登录的时候, session保存的值进行,一番修改:

    def init_permission(current_user, request):
        '''  二级菜单,实现
        :param current_user: 当前请求 用户对象
        :param request:  当前请求 数据
        :return:
        '''
        # 2. 权限 初始化
        # 根据当前用户信息,获取当前用户所拥有的所有的权限(queryset对象 是不能直接放入,session中的)
        permission_queryset = current_user.roles.filter(permissions__isnull=False) 
            .values("permissions__id", "permissions__url", "permissions__title", "permissions__pid_id",
                    "permissions__menu_id", "permissions__menu__icon", "permissions__menu__title", ).distinct()
    
        # 获取权限 和 菜单信息。  权限放在权限列表,菜单放在菜单列表
        menu_dict = {}
        permission_list = []  # 这里就不再是一个 单纯的列表! 而是套嵌字典的列表
        for item in permission_queryset:
            url_dict = {
                "id": item.get("permissions__id"),
                "url": item.get("permissions__url"),
                "paren_id": item.get("permissions__pid_id")
            }
            permission_list.append(url_dict)
    
            menu_id = item.get("permissions__menu_id")
            if not menu_id:
                continue
    
            node = {"id": item.get("permissions__id"), "title": item.get("permissions__title"),
                    "url": item.get("permissions__url")}
            if menu_id in menu_dict:
                menu_dict[menu_id]["children"].append(node)
            else:
                menu_dict[menu_id] = {
                    "title": item.get("permissions__menu__title"),
                    "icon": item.get("permissions__menu__icon"),
                    "children": [node]
                }
        request.session[settings.PERMISSIONS_SESSION_KEY] = permission_list
        request.session[settings.MENU_SESSION_KEY] = menu_dict
    对init_permission 初始化权限列表,和 菜单字典时。做一点修改

    3. 然后是,中间件部分的,处理:
      这里 我们需要读取出,当前访问的url (通过 request.path_info)。 然后与权限列表中的所有url 进行匹配。
    匹配成功之后。这一步很重要:我们需要一个参数( 一个应该被选中的id 或 parent_id),传递给 inclusion_tag。 如何传递呢?
        request.current_selected_permission = item.get("paren_id") or item.get("id")
      在匹配成功之后,进行这一步操作。 在 request 对象中,添加一个属性current_selected_permission 他的值是 tem.get("paren_id") or item.get("id")
      这个 参数的作用就是,判断。那一个子菜单应该默认被选中 或者 被展开。 or 的语法 不做多余解释。

    4. 最后就是 自定义的 模板语法了:

    @register.inclusion_tag("rbac/multi_menu.html")
    def multi_menu(request):
        '''
        创建二级菜单
        :return:
        '''
        current_selected_permission = request.current_selected_permission
        path_info = request.path_info
        menu_dict = request.session.get(settings.MENU_SESSION_KEY)
    
        key_list = sorted(menu_dict)  # 对字典的key 进行排序
        ordered_dict = OrderedDict()  # 创建一个空的 有序字典
        for key in key_list:   # 循环有序字典列表
            val = menu_dict[key]  # 得到每一个字典
            val["class"] = "hide"  # 添加一个 class:hide 键值. 控制标签的显示隐藏
            for per in val["children"]:  # 循环 当前字典(菜单) 下的 子菜单
                if per.get("id") == current_selected_permission:
                    per["class"] = "active"   # 匹配成功 为当前子菜单添加  class:active 类属性(表示被选中的)
                    val["class"] = ""  # 当前一级菜单的 class:""  跟改为空, 覆盖掉hide(不隐藏)
            ordered_dict[key] = val  # 最终将设置好的每一个字典。 添加到有序字典当中
    
        return {"ordered_dict": ordered_dict, "path_info": path_info}
    改动之后的, rbac_tags

    这里做个什么改动呢:
      就只有一点, 将原来判断, 当前访问的 url 与 每一个子菜单的url 进行匹配的操作。
        改成了  per.get("id") == current_selected_permission   当前访问的url 的 id 或他的 parent_id 与 保存的 应该展开显示的 子菜单url的 主键id。进行匹配。
      匹配成功的这条子菜单权限 url 自己添加 class="active" 并且他的父级 删除掉 hide  "class" = ""。

  • 相关阅读:
    Vue.Draggable实现拖拽效果(快速使用)
    1.从面向过程到面向对象的过渡
    微信支付流程
    2.js原型的基本概念
    POST和GET请求的区别
    vue-router2.0
    vue列表渲染,以及鼠标点击改变样式的问题
    复杂数组结构的深拷贝
    高德地图将字符串地址转为经纬度的一个demo
    数组对象排序
  • 原文地址:https://www.cnblogs.com/chengege/p/10702055.html
Copyright © 2011-2022 走看看