Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

支持导航菜单动态配置 #3290

Open
maobuji opened this issue Jun 22, 2020 · 8 comments
Open

支持导航菜单动态配置 #3290

maobuji opened this issue Jun 22, 2020 · 8 comments
Assignees
Milestone

Comments

@maobuji
Copy link

maobuji commented Jun 22, 2020

在某些项目中,需要根据用户场景,重新组织菜单结构,这样对造成产品的多分支,部署也比较麻烦。
另外有时需要在菜单中增加外链,如果采用目前的配置方式也需要修改代码才可以,而且也无法进行权限的配置。

是否能够提供可以配置菜单的功能?菜单在后台配置,用户在登录时获取对应结构菜单结构进行展现。
希望有一个动态的切入点,能够加载外部递送的菜单,并将其与静态菜单结合。这样无论采用静态菜单还是动态菜单,都不用修改ice的源代码了。后续升级也会比较方便。

@Pratham31
Copy link

Will you send the corresponding Project link so I can help you out :)

@imsobear
Copy link
Collaborator

涉及到两个点:

  1. Layout 更好的封装性(目前散落在业务里的代码太多了)
  2. 菜单数据的动态获取和下发,理论上是走 getInitialData 的通道,layout 里怎么拿到需要有个方案,比如之前提过的提供一个 API

@luhc228
Copy link
Collaborator

luhc228 commented Sep 10, 2020

背景

  1. Layout 相关配置代码太多了,并分散在各文件中
  2. 对于前端新手来说配置 Layout 的成本太高
  3. 缺少动态菜单和静态菜单的结合

方案一

介绍

  • 基于 fusion design 的 Shell 组件作为 Layout,封装 IceLayout组件( npm 包 ice-layout),支持传入 config 配置至组件中
  • 支持菜单栏的动态配置

使用

Layout 配置

header

title: layout 的左上角的 title

logo: layout 左上角 logo url

  • Type: { title: string | ReactNode, logo: string | ReactNode }
  • Default: { title: 'ICE', logo: 'https://ice.work' }
headerMenuConfig

顶部菜单栏的配置

asideMenuConfig

侧边菜单栏的配置

headerRightRender

头部右侧展示的组件 默认展示头像组件

  • Type: React.ReactNode | null
  • Default: 展示用户名、头像、退出登录相关组件
menuMode

菜单模式:side: 左侧导航,top: 顶部导航

  • Type: 'side' | 'top'
  • Default: 'side'
menuData

侧边栏或顶部栏菜单配置,用于异步获取服务端的菜单数据并和静态的菜单数据进行合并。当设置该属性时,不会读取 asideMenuConfigheaderMenuConfig,而是直接读取该函数返回的内容

  • Type: async () => IMenuConfig[]
  • Default: undefined

IMenuConfig 数据结构

interface IMenuConfig {
  name: string;
  path: string;
  icon?: string;
  children?: IMenuConfig[]
}
menuSettings

详见 Shell.Navigation

  • collapse 是否折叠(折叠成只有icon状态)
  • align 横向模式下,导航排布的位置
  • onCollapseChange 默认按钮触发的展开收起状态
  • trigger 菜单展开、收起的触发元素
  • fixed 是否固定
menuRender

菜单 render 方法

  • Type: React.ReactNode
  • Default: null
footerRender

底部组件 render 方法

  • Type: React.ReactNode
  • Default: null
settings
  • device:预设的屏幕宽度
  • type:布局主题
  • fixedHeader:是否固定Header
  1. BasicLayout/index.jsx 中引入 IceLayout 组件,并引入相应的属性。另外还支持在 BasicLayout 目录下新建 config.jsx,便于 Iceworks 后续可视化 Layout 配置:
// src/BasicLayout/index.jsx 
import React from 'react';
import IceLayout from 'ice-layout';
import config from './config';

// 或者直接写组件的 props
export default <IceLayout footerRender={<Footer />} header={ title: 'ICE' } ... />

// export default <IceLayout {...config} />
  1. 新建 config.jsx 文件用于配置 Layout:
// src/layouts/BasicLayout/config.js
import React from 'react';
import Footer from './Footer';

export default {
  header: {
    title: 'ICE',
    logo: 'https://ice.work'
  },
  headerRightRender: (
    <>
      <Notice />
      <HeaderAvatar />
    </>
  ),
  settings: {
  	device: 'phone',
 	  type: 'dark',
  },
  // navigation(菜单)配置
  menuSettings: {
   collapse: true
  },
  headerMenuConfig: [],
  asideMenuConfig: [
    {
      name: '数据页面',
      path: '/',
      icon: 'chart-pie',
      children: [
        {
          name: '分析页面',
          path: '/dashboard/analysis',
        },
      ]
    },
  ],
  footerRender: <Footer />
}

菜单栏动态配置

获取动态菜单与静态菜单结合,在 config.jsx 中配置菜单:

// src/layouts/BasicLayout/config.js
import React from 'react';

export default {
  menuData: async function() {
    // 模拟服务端返回的数据
    const data = await request('/api/menu');
    const { customMenu } = data;
  	return [
      // 服务器获取的菜单数据
      ...customMenu.asideMenuConfig,
      // 静态的菜单数据
      ...this.asideMenuConfig
    ],
  }
}

方案二

介绍

  • 基于 fusion design 的 Shell 组件作为 Layout,将布局通过 icejs 插件(build-plugin-ice-layout )的方式内置
  • 通过在 src/app.jsx 中配置布局相关的属性,生成对应 Layout 至 .ice\layouts 文件夹中
  • src/routes.js 文件中,通过 import { BasicLayout } from 'ice' 的方式引入 Layout 组件
  • 支持菜单栏的动态配置
  • 结合 build-plugin-ice-auth 插件,支持菜单栏权限配置

使用

Layout 配置

相关的参数配置同上

  1. src/app.jsx 中配置:
// src/app.jsx
import React from 'react';
import { createApp } from 'ice';

const appConfig = {
 layout: [{
      // Layout 名称
      name: 'BasicLayout',
      header: {
        title: 'ICE',
        logo: 'https://ice.work'
      },
      headerRightRender: (initialState) => {
        return (
          <>
            <Notice />
            <HeaderAvatar />
          </>
        )
      },
      settings: {
        device: 'phone',
        type: 'dark',
      },
      // navigation(菜单)配置
      menuSettings: {
       collapse: true
      },
      // menu 菜单配置
      menuData: () => {
        return [
            {
              name: '数据页面',
              path: '/',
              icon: 'chart-pie',
              children: [
                {
                  name: '分析页面',
                  path: '/dashboard/analysis',
                },
             },
          ]
      },
      footerRender: () => <Footer />
    },
  ],  
}

createApp(appConfig);
  1. src/routes.js 文件中引入 Layout 组件:
import { BasicLayout } from 'ice';

const routerConfig = [
  {
    path: '/',
    component: BasicLayout,
    children: [
      { path: '/hello', component: Hello },
    ],
  },
]

菜单栏动态配置

  1. 获取初始化的菜单信息:相关配置同上

  2. src/app.jsx 配置静态菜单

// src/app.jsx
   
import { createApp } from 'ice';
   
const appConfig = {
   layout: [{
         // Layout 名称
         name: 'BasicLayout',
        // menu 菜单配置
        menuData: ({ menu }) => {
          return [
              {
                name: '数据页面',
                path: '/',
                icon: 'chart-pie',
                children: [
                  {
                    name: '分析页面',
                    path: '/dashboard/analysis',
                  },
               },
               ...menu.asideMenuConfig
            ]
        },
      }
   ],  
}
   
createApp(appConfig);

总结

方案一

不依赖 icejs,直接用一个组件包来封装 Layout。另外可以新建一个 config.jsx作为 layout 的配置,后续便于 Iceworks 可视化 layout 配置,并修改配置。

方案二

需要在 icejs 上增加插件,额外在 app.jsx文件中增加配置内容,复杂度太高,不利于维护。

@chenbin92
Copy link
Collaborator

chenbin92 commented Sep 10, 2020

需要下考虑权限的处理方式

@luhc228
Copy link
Collaborator

luhc228 commented Sep 11, 2020

需要下考虑权限的处理方式

方案 updated

@alvinhui
Copy link
Collaborator

  • 方案一是否可以覆盖常见模板的布局?
  • 方案二的使用方式不太好,又引入了一个私有变量

@luhc228
Copy link
Collaborator

luhc228 commented Sep 16, 2020

  • 是否可以覆盖常见模板的布局

方案1,目前设计的方案是不可以覆盖常见模板的布局。想法是覆盖大部分的使用场景即可,有定制需求使用原始的 Layout 方案。

@luhc228
Copy link
Collaborator

luhc228 commented Sep 16, 2020

最终讨论结果是使用第一个方案

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants