''' Author: your name Date: 2021-07-27 16:19:06 LastEditTime: 2021-07-28 09:23:23 LastEditors: your name Description: In User Settings Edit FilePath: \evm-store\tools\build_out\models\menu.py ''' #!/usr/bin/env python # -*- coding: utf_8 -*- import copy from application.app import db, ma from .base import PrimaryModel from marshmallow import Schema, fields, INCLUDE, EXCLUDE class MenuModel(PrimaryModel): __tablename__ = 'evm_menu' name = db.Column(db.String(100), nullable = True) parent_id = db.Column(db.Integer, default=0, nullable = True) path = db.Column(db.String(100), nullable = True) disabled = db.Column(db.Boolean, nullable = True, default = False) fixed = db.Column(db.Boolean, nullable = False, default = False) has_children = db.Column(db.Boolean, nullable = True, default = False) icon = db.Column(db.String(100), nullable = True, default = '') # __table_args__ = ( # db.Index('idx_xxx', 'xxx', mysql_using='btree'), # ) def __init__(self, name, parentId, path, disabled=False, fixed=False, hasChildren=False, icon=''): self.name = name self.parent_id = parentId self.path = path self.disabled = disabled self.fixed = fixed self.has_children = hasChildren self.icon = icon def __repr__(self): return '<MenuModel %r>' % (self.name) def to_dict(self): return { 'id': self.id, 'name': self.name, 'parentId': self.parent_id, 'path': self.path, 'disabled': self.disabled, 'fixed': self.fixed, 'hasChildren': self.has_children, 'icon': self.icon, 'sort': self.sort, 'remark': self.remark, 'deleted': self.is_delete, 'createUser': self.create_by, 'updateUser': self.update_by, 'createTime': self.create_at.strftime("%Y-%m-%d %H:%M:%S") if self.create_at else None, "updateTime": self.update_at.strftime("%Y-%m-%d %H:%M:%S") if self.update_at else None, } class TreeMenuNode: """树形菜单节点""" def __init__(self, pk, title, code, icon_class, url, order, child, parent): self.pk = pk self.title = title self.code = code self.icon_class = icon_class self.url = url self.order = order self.child = child self.parent = parent def count(self): if not self.child: return 0 return len(self.child) class HandleTreeMenu: """处理树形侧边栏菜单""" def __init__(self, menus): self.menus = menus self.tree_menu = [] def __iter__(self): if self.tree_menu: return iter(self.tree_menu) return iter([]) @staticmethod def get_complete_menu_structure(_menu_list): """得到完整的菜单结构""" menu_list = copy.copy(_menu_list) for menu in menu_list: if menu.parent and menu.parent not in menu_list: menu_list.append(menu.parent) menu_list.extend(HandleTreeMenu.get_complete_menu_structure(menu_list)) return menu_list def convert_to_tree(self): """转换BaseQuery为MenuTree结构""" complete_menu = HandleTreeMenu.get_complete_menu_structure(self.menus) # 所有顶级菜单 top_menu = [menu for menu in complete_menu if not menu.parent] for menu in top_menu: current_menu = TreeMenuNode(menu.pk, menu.title, menu.code, menu.icon_class, menu.url, menu.order, [], None) current_menu = self._recursive_menu(menu, current_menu) self.tree_menu.append(current_menu) def _recursive_menu(self, base_menu, base_tree_menu): """由上往下递归菜单得到所有菜单并转换为TreeMenuNode格式""" complete_menu = HandleTreeMenu.get_complete_menu_structure(self.menus) child_menu = [menu for menu in complete_menu if menu.parent == base_menu] # 父节点为base_menu的子节点 for menu in child_menu: current_menu = TreeMenuNode(menu.pk, menu.title, menu.code, menu.icon_class, menu.url, menu.order, [], base_tree_menu) current_menu = self._recursive_menu(menu, current_menu) base_tree_menu.child.append(current_menu) return base_tree_menu if __name__ == '__main__': # 使用方法 menus = MenuModel.query.all() # 这里是直接在数据库里面查询出来的, 用户私有权限表 tree_menu = HandleTreeMenu(menus)# 创建一个对象 tree_menu.convert_to_tree() # 执行转换方法 print(tree_menu.tree_menu) # 得到已经转换的菜单