From 7d1c97aadf764290f3faeb99483bcf33aa5ae85d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=87=E7=BA=AF?= Date: Mon, 8 Mar 2021 15:30:34 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96plugin-layout,?= =?UTF-8?q?=E5=9C=A8=E7=BC=96=E8=AF=91=E6=97=B6=E6=8E=A2=E6=B5=8B=E9=9C=80?= =?UTF-8?q?=E8=A6=81=E7=9A=84icon=E7=BB=84=E4=BB=B6,=E7=84=B6=E5=90=8E?= =?UTF-8?q?=E6=8C=89=E9=9C=80=E5=8A=A0=E8=BD=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/fes-plugin-layout/src/index.js | 23 ++++++++++++- .../helpers/index.js => node/helper.js} | 32 +++++++++++++++++-- .../fes-plugin-layout/src/runtime/index.tpl | 5 +-- .../src/runtime/views/Menu.vue | 2 +- .../src/runtime/views/MenuIcon.vue | 26 ++++++--------- 5 files changed, 62 insertions(+), 26 deletions(-) rename packages/fes-plugin-layout/src/{runtime/helpers/index.js => node/helper.js} (60%) diff --git a/packages/fes-plugin-layout/src/index.js b/packages/fes-plugin-layout/src/index.js index 8d4d47be..99325149 100644 --- a/packages/fes-plugin-layout/src/index.js +++ b/packages/fes-plugin-layout/src/index.js @@ -9,6 +9,8 @@ export default (api) => { utils: { Mustache } } = api; + const helper = require('./node/helper'); + api.describe({ key: 'layout', config: { @@ -25,7 +27,7 @@ export default (api) => { const absRuntimeFilePath = join(namespace, 'runtime.js'); - api.onGenerateFiles(() => { + api.onGenerateFiles(async () => { const { name } = api.pkg; const HAS_LOCALE = api.hasPlugins(['@fesjs/plugin-locale']); @@ -37,6 +39,25 @@ export default (api) => { ...(api.config.layout || {}) }; + // 路由信息 + const routes = await api.getRoutes(); + // 把路由的meta合并到menu配置中 + userConfig.menus = helper.fillMenuByRoute(userConfig.menus, routes); + + const icons = helper.getIconsFromMenu(userConfig.menus); + + const iconsString = icons.map( + iconName => `import ${iconName} from '@ant-design/icons-vue/es/icons/${iconName}'` + ); + api.writeTmpFile({ + path: join(namespace, 'icons.js'), + content: ` + ${iconsString.join(';\n')} + export default { + ${icons.join(',\n')} + }` + }); + api.writeTmpFile({ path: absFilePath, content: Mustache.render( diff --git a/packages/fes-plugin-layout/src/runtime/helpers/index.js b/packages/fes-plugin-layout/src/node/helper.js similarity index 60% rename from packages/fes-plugin-layout/src/runtime/helpers/index.js rename to packages/fes-plugin-layout/src/node/helper.js index a9795055..5b69e83b 100644 --- a/packages/fes-plugin-layout/src/runtime/helpers/index.js +++ b/packages/fes-plugin-layout/src/node/helper.js @@ -1,4 +1,4 @@ -export const noop = () => {}; +import * as allIcons from '@ant-design/icons-vue'; const matchName = (config, name) => { let res = {}; @@ -21,7 +21,7 @@ const matchName = (config, name) => { return res; }; -export const fillMenuData = (menuConfig, routeConfig, dep = 0) => { +export const fillMenuByRoute = (menuConfig, routeConfig, dep = 0) => { dep += 1; if (dep > 3) { throw new Error('[plugin-layout]: menu层级不能超出三层!'); @@ -39,11 +39,37 @@ export const fillMenuData = (menuConfig, routeConfig, dep = 0) => { menu[prop] = pageConfig[prop]; } }); + // 处理icon + if (menu.icon) { + const icon = menu.icon; + const iconName = `${icon.replace(icon[0], icon[0].toUpperCase())}Outlined`; + if (!allIcons[icon]) { + menu.icon = iconName; + } + } if (menu.children && menu.children.length > 0) { - menu.children = fillMenuData(menu.children, routeConfig, dep); + menu.children = fillMenuByRoute(menu.children, routeConfig, dep); } arr.push(menu); }); } return arr; }; + +export function getIconsFromMenu(data) { + if (!Array.isArray(data)) { + return []; + } + let icons = []; + (data || []).forEach((item = { path: '/' }) => { + if (item.icon) { + const { icon } = item; + icons.push(icon); + } + if (item.children) { + icons = icons.concat(getIconsFromMenu(item.children)); + } + }); + + return Array.from(new Set(icons)); +} diff --git a/packages/fes-plugin-layout/src/runtime/index.tpl b/packages/fes-plugin-layout/src/runtime/index.tpl index 55f2fd09..ce86b74a 100644 --- a/packages/fes-plugin-layout/src/runtime/index.tpl +++ b/packages/fes-plugin-layout/src/runtime/index.tpl @@ -1,7 +1,6 @@ import { reactive, defineComponent } from "vue"; -import { getRoutes, plugin, ApplyPluginsType } from "@@/core/coreExports"; +import { plugin, ApplyPluginsType } from "@@/core/coreExports"; import BaseLayout from "./views/BaseLayout.vue"; -import { fillMenuData } from "./helpers"; const userConfig = reactive({{{REPLACE_USER_CONFIG}}}); @@ -14,8 +13,6 @@ const Layout = defineComponent({ initialValue: {}, }); const localeShared = plugin.getShared("locale"); - const routeConfig = getRoutes(); - userConfig.menus = fillMenuData(userConfig.menus, routeConfig); return () => { const slots = { customHeader: () => { diff --git a/packages/fes-plugin-layout/src/runtime/views/Menu.vue b/packages/fes-plugin-layout/src/runtime/views/Menu.vue index 05b4403f..264ae82a 100644 --- a/packages/fes-plugin-layout/src/runtime/views/Menu.vue +++ b/packages/fes-plugin-layout/src/runtime/views/Menu.vue @@ -50,7 +50,7 @@ import { toRefs, computed } from 'vue'; import { useRoute, useRouter } from '@@/core/coreExports'; import Menu from 'ant-design-vue/lib/menu'; import 'ant-design-vue/lib/menu/style/css'; -import MenuIcon from './MenuIcon' +import MenuIcon from './MenuIcon'; import { addAccessTag } from '../helpers/pluginAccess'; export default { diff --git a/packages/fes-plugin-layout/src/runtime/views/MenuIcon.vue b/packages/fes-plugin-layout/src/runtime/views/MenuIcon.vue index 1422f39d..d04c8f03 100644 --- a/packages/fes-plugin-layout/src/runtime/views/MenuIcon.vue +++ b/packages/fes-plugin-layout/src/runtime/views/MenuIcon.vue @@ -2,29 +2,21 @@ // 使用 ant-design/icons-vue // 使用 本地 svg 图片 // 使用 远程 svg 地址 -import { ref, onMounted } from 'vue'; +// eslint-disable-next-line import/extensions +import Icons from '../icons'; // import AntdIcon from '@ant-design/icons-vue/es/components/AntdIcon'; export default { props: { icon: String }, setup(props) { - const AIcon = ref(null); - onMounted(()=>{ - const iconName = props.icon.slice(0, 1).toUpperCase() + props.icon.slice(1) + 'Outlined'; - import(`@ant-design/icons-vue/es/icons/${iconName}`).then(res=>{ - AIcon.value = res.default; - }).catch(e=>{ - console.warn(`[fes-layout] icon ${props.icon} 不存在!`) - }) - }) - return ()=>{ - if(AIcon.value){ - return + const AIcon = Icons[props.icon]; + return () => { + if (AIcon) { + return < AIcon />; } - return null - } - + return null; + }; } -} +};