Skip to content

动态生成菜单

首先修改 static/config/pear.config.json 文件里面引用的地址

json
  "menu": {
    "data": "/static/admin/data/menu.json", 
    "data": "/api/v1/menu", 
    "method": "GET",
    "accordion": true,
    "collapse": false,
    "control": false,
    "controlWidth": 500,
    "select": "10", 
    "select": "126", 
    "async": true
  },
  "tab": {
    "enable": true,
    "keepState": true,
    "session": true,
    "preload": true,
    "max": "30",
    "index": {
      "id": "10", 
      "id": "126", 
      "href": "view/analysis/index.html",
      "title": "首页"
    }
  },

编写动态生成菜单的接口。

python
@passport_api.get("/menu")
@jwt_required()
def menus_api():
    rights_orm_list = set()
    current_user: UserORM = get_current_user()
    for role in current_user.role_list:
        for rights_orm in role.rights_list:
            if rights_orm.type != "auth":
                rights_orm_list.add(rights_orm)

    rights_list = [rights_orm.menu_json() for rights_orm in rights_orm_list]
    rights_list.sort(key=lambda x: (x["pid"], x["id"]), reverse=True)

    menu_dict_list = OrderedDict()
    for menu_dict in rights_list:
        if menu_dict["id"] in menu_dict_list.keys():  # 如果当前节点已经存在与字典中
            # 当前节点添加子节点
            menu_dict["children"] = deepcopy(menu_dict_list[menu_dict["id"]])
            menu_dict["children"].sort(key=lambda item: item["sort"])
            # 删除子节点
            del menu_dict_list[menu_dict["id"]]

        if menu_dict["pid"] not in menu_dict_list:
            menu_dict_list[menu_dict["pid"]] = [menu_dict]
        else:
            menu_dict_list[menu_dict["pid"]].append(menu_dict)

    return sorted(menu_dict_list.get(0), key=lambda item: item["sort"])

配置文件修改与说明

在说配置文件之前,有三个小优化点需要提前讲一下

  1. 可以在 index.html 中给 html 标签添加 lang='zh-CN',每次刷新时就不会弹出翻译提示了。

  2. 对初始化的数据做了一些调整,不影响使用。

  3. flask-jwt-extended 默认过期时间只有十五分钟,应该放到 BaseConfig 当中

    python
    class BaseConfig:
        SECRET_KEY = os.getenv("SECRET_KEY", "pear-admin-flask")
    
        SQLALCHEMY_DATABASE_URI = ""
    
        ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
    
        JWT_TOKEN_LOCATION = ["headers"]  
        JWT_ACCESS_TOKEN_EXPIRES = timedelta(days=7) 

然后再来看前端的配置文件

json
{
  "logo": {
    "title": "Pear Admin Flask", // 项目标题
    "image": "/static/admin/images/logo.png" // 菜单栏收起时展示的图片
  },
  "menu": {
    "data": "/api/v1/menu",  // 菜单的数据接口
    "method": "GET",
    "accordion": true,
    "collapse": false,
    "control": false,
    "controlWidth": 500,
    "select": "10", 
    "select": "126", // 默认选中的菜单 ID
    "async": true
  },
  "tab": {  // tab 标签导航栏
    "enable": true,
    "keepState": true,
    "session": true,
    "preload": false,
    "max": "30",
    "index": {  // 默认选中的菜单信息
      "id": "126",
      "href": "view/analysis/index.html",
      "title": "首页"
    }
  },
  "theme": {
    "defaultColor": "2", // 默认选中的系统主题色
    "defaultColor": "1", 
    "defaultMenu": "dark-theme",
    "defaultHeader": "light-theme",
    "allowCustom": true,
    "banner": false
  },
  "colors": [
    {
      "id": "1",
      "color": "#2d8cf0",  // 主配色,可以自行调整
      "color": "#16baaa",  
      "second": "#ecf5ff"
    },
    {
      "id": "2",
      "color": "#36b368",
      "second": "#f0f9eb"
    },
    {
      "id": "3",
      "color": "#f6ad55",
      "second": "#fdf6ec"
    },
    {
      "id": "4",
      "color": "#f56c6c",
      "second": "#fef0f0"
    },
    {
      "id": "5",
      "color": "#3963bc",
      "second": "#ecf5ff"
    }
  ],
  "other": {
    "keepLoad": "1200",
    "autoHead": false,
    "footer": false
  },
  "header": {
    "message": "/static/admin/data/message.json"
  }
}