一、前言
菜单管理主要管理用户菜单和权限,可以给菜单增加权限,只有有权限的用户才能操作。
二、后端实现
直接在menu.py中编写
# !/usr/bin/python3 # -*- coding: utf-8 -*- """ @Author : Huguodong @Version : ------------------------------------ @File : menu_route.py @Description : 菜单方面的请求 @CreateTime : 2020/3/8 15:55 ------------------------------------ @ModifyTime : """ from permission import * menu = Blueprint('menu', __name__) @menu.route('/find_all_menu', methods=["POST"]) # @login_required def find_all_menu(): ''' 根据用户id获取菜单 :return: ''' res_dir = request.get_json() user_id = res_dir.get("uuid") data = constructMenuTrees(user_id=user_id) # 获取菜单树 return jsonify(code=Code.SUCCESS.value, msg="ok", data=data) @menu.route('/menus', methods=["POST"]) def menus(): ''' 获取菜单信息 :param:{"menu_name":"菜单","visible":0,"page":1,"page_size":10,"order_column_name":"","order_type":""} :return: ''' res_dir = request.get_json() if res_dir is None: return NO_PARAMETER() visible = res_dir.get("visible") menu_name = res_dir.get("menu_name") page = res_dir.get("page") page_size = res_dir.get("page_size") # 如果没有查询条件,则返回全部数据 if not visible and not menu_name: data = constructMenuTrees() # 获取菜单树 return jsonify(code=Code.SUCCESS.value, msg="ok", data=data) else: if not page or page <= 0: page = 1 if not page_size or page_size <= 0: page_size = 10 if visible == 0: visible = (1, 2) else: visible = (visible,) # 根据条件查询,并分页 menu_data = Menu.query.filter( Menu.menu_name.like("%" + menu_name + "%") if menu_name is not None else "", Menu.visible.in_(visible), ).order_by('menu_name').paginate(page, page_size, error_out=False) data = construct_menu_data(menu_data) # 格式化返回数据 return jsonify(code=Code.SUCCESS.value, msg="ok", data=data) @menu.route('/create', methods=["PUT"]) def create(): ''' 新建菜单或权限 :return: ''' res_dir = request.get_json() if res_dir is None: return NO_PARAMETER() # 根据token获取用户id try: token = request.headers["Authorization"] user = verify_token(token) menu = Menu() menu.parent_id = res_dir.get("parent_id"), menu.menu_name = res_dir.get("menu_name"), menu.menu_type = res_dir.get("menu_type"), menu.icon = res_dir.get("icon"), menu.is_frame = res_dir.get("is_frame"), menu.url = res_dir.get("url"), menu.route_name = res_dir.get("route_name"), menu.route_path = res_dir.get("route_path"), menu.route_component = res_dir.get("route_component"), menu.route_cache = res_dir.get("route_cache"), menu.perms = res_dir.get("perms"), menu.visible = res_dir.get("visible"), menu.order_num = res_dir.get("order_num"), menu.remark = res_dir.get("remark"), menu.create_by = user['name'], menu.save() return SUCCESS() except Exception as e: app.logger.error(f"新建菜单失败:{e}") return CREATE_ERROR() @menu.route('/delete', methods=["DELETE"]) def delete(): ''' 根据id删除菜单或权限 :return: ''' res_dir = request.get_json() if res_dir is None: return NO_PARAMETER() menu_id = res_dir.get("id") if menu_id: try: parent = Menu.query.filter_by(parent_id=menu_id).all() if parent: return DELETE_ERROR(msg="该菜单下存在子菜单,无法删除!") role = Role_Menu.query.filter_by(menu_id=menu_id).all() if role: return DELETE_ERROR(msg="该菜单已与角色关联,无法删除!") menu = Menu.query.get(menu_id) if menu: menu.delete() return SUCCESS() else: return ID_NOT_FOUND() except Exception as e: app.logger.error(f"删除菜单失败:{e}") return DELETE_ERROR() else: return PARAMETER_ERR() @menu.route('/update', methods=["POST", "PUT"]) def update(): ''' 更新菜单或权限 POST方法根据id返回数据 PUT方法更新菜单或权限 :return: ''' res_dir = request.get_json() if res_dir is None: return NO_PARAMETER() if request.method == "POST": menu_id = res_dir.get("id") if id: menu = Menu.query.get(menu_id) if menu: menu_data = model_to_dict(menu) return SUCCESS(menu_data) else: return ID_NOT_FOUND() else: PARAMETER_ERR() if request.method == "PUT": menu_id = res_dir.get("id") menu_name = res_dir.get("menu_name") if id and menu_name: model = Menu.query.get(menu_id) if model: token = request.headers["Authorization"] user = verify_token(token) model.parent_id = res_dir.get("parent_id") model.menu_name = res_dir.get("menu_name") model.menu_type = res_dir.get("menu_type") model.icon = res_dir.get("icon") model.is_frame = res_dir.get("is_frame") model.url = res_dir.get("url") model.route_name = res_dir.get("route_name") model.route_path = res_dir.get("route_path") model.route_component = res_dir.get("route_component") model.route_cache = res_dir.get("route_cache") model.perms = res_dir.get("perms") model.visible = res_dir.get("visible") model.order_num = res_dir.get("order_num") model.remark = res_dir.get("remark") model.update_by = user['name'] try: model.update() return SUCCESS() except Exception as e: app.logger.error(f"更新菜单失败:{e}") return UPDATE_ERROR() else: return ID_NOT_FOUND() else: return PARAMETER_ERR() def constructMenuTrees(parentId=0, user_id=None): ''' 通过递归实现根据父ID查找子菜单,如果传入用户id则只查询该用户的权限否则查询所有权限,一级菜单父id默认是0 1.根据父ID获取该菜单下的子菜单或权限 2.遍历子菜单或权限,继续向下获取,直到最小级菜单或权限 3.如果没有遍历到,返回空的数组,有返回权限列表 :param user_id: :param parentId: :return:dict ''' if user_id: menu_data = Menu.query.join(Role_Menu, Menu.id == Role_Menu.menu_id).join(User_Role, User_Role.role_id == Role_Menu.role_id).filter( User_Role.user_id == user_id).filter(Menu.parent_id == parentId).order_by('order_num').all() else: menu_data = Menu.query.filter(Menu.parent_id == parentId).order_by('order_num').all() menu_dict = menu_to_dict(menu_data) if len(menu_dict) > 0: data = [] for menu in menu_dict: menu['children_list'] = constructMenuTrees(menu['id'], user_id) data.append(menu) return data return [] def menu_to_dict(result): ''' 格式化菜单字段显示顺序 :param result: :return: ''' data = [] for menu in result: child = { "id": menu.id, "menu_name": menu.menu_name, "parent_id": menu.parent_id, "order_num": menu.order_num, "url": menu.url, "menu_type": menu.menu_type, "visible": menu.visible, "perms": menu.perms, "icon": menu.icon, "is_frame": menu.is_frame, "create_by": menu.create_by, "created_at": menu.created_at, "update_by": menu.update_by, "updated_at": menu.updated_at, "remark": menu.remark, "route_name": menu.route_name, "route_path": menu.route_path, "route_cache": menu.route_cache, "route_component": menu.route_component, } data.append(child) return data