From a9e76dc2bbd56a61eed4b745c43ae5904512ddfa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=87=E7=BA=AF?= Date: Mon, 15 Mar 2021 16:43:02 +0800 Subject: [PATCH] =?UTF-8?q?feat(plugin-layout):=20=20=E8=8F=9C=E5=8D=95?= =?UTF-8?q?=E7=9A=84=20icon=E6=94=AF=E6=8C=81svg=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E3=80=81title=E6=94=AF=E6=8C=81=E5=9B=BD=E9=99=85=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/zh/reference/plugin/plugins/layout.md | 18 +++++- packages/fes-plugin-layout/README.md | 1 - packages/fes-plugin-layout/src/node/helper.js | 20 +++++-- .../src/runtime/helpers/svg.js | 49 ++++++++++++++++ .../src/runtime/views/Menu.vue | 29 ++++++---- .../src/runtime/views/MenuIcon.vue | 56 ++++++++++++++++--- .../fes-plugin-locale/src/runtime/core.tpl | 2 +- packages/fes-template/.fes.js | 2 +- packages/fes-template/public/wine-outline.svg | 1 + packages/fes-template/src/locales/en-US.js | 1 + packages/fes-template/src/locales/zh-CN.js | 1 + packages/fes-template/src/pages/index.vue | 2 +- 12 files changed, 153 insertions(+), 29 deletions(-) create mode 100644 packages/fes-plugin-layout/src/runtime/helpers/svg.js create mode 100644 packages/fes-template/public/wine-outline.svg diff --git a/docs/zh/reference/plugin/plugins/layout.md b/docs/zh/reference/plugin/plugins/layout.md index e0511b54..85bd8885 100644 --- a/docs/zh/reference/plugin/plugins/layout.md +++ b/docs/zh/reference/plugin/plugins/layout.md @@ -9,6 +9,8 @@ - 搭配 [@fesjs/plugin-access](./access.html) 插件使用,可以完成对路由的权限控制。 - 搭配 [@fesjs/plugin-locale](./locale.html) 插件使用,提供切换语言的能力。 - 支持自定义头部区域。 +- 菜单支持配置icon +- 菜单标题支持国际化 - 可配置页面是否需要 layout。 @@ -156,9 +158,21 @@ export default { - **path**:菜单的路径,可配置第三方地址。 - - **title**:菜单的标题。 + - **title**:菜单的标题,如果同时使用[国际化插件](./locale.md),而且在 `locales` 中配置了 `title` ,则菜单的名称会根据语言自动切换。 - - **icon**: 菜单的图标,只有一级标题展示图标,图标使用[antv icon](https://www.antdv.com/components/icon-cn/),在这里使用组件type。 + - **icon**: 菜单的图标,只有一级标题展示图标。 + - 图标使用[antv icon](https://www.antdv.com/components/icon-cn/),在这里使用组件type。 +```js +{ + name: "user" +} +``` + - 图表使用本地或者远程svg图片。 +```js +{ + name: "/wine-outline.svg" +} +``` - **children**:子菜单配置。 diff --git a/packages/fes-plugin-layout/README.md b/packages/fes-plugin-layout/README.md index 3dd57ad4..5bcd3b30 100644 --- a/packages/fes-plugin-layout/README.md +++ b/packages/fes-plugin-layout/README.md @@ -5,7 +5,6 @@ multi tabs: 是/否 ## todo-list -1. 菜单的国际化 ### theme 1. 主题light-白色 diff --git a/packages/fes-plugin-layout/src/node/helper.js b/packages/fes-plugin-layout/src/node/helper.js index cc1efbac..6065365d 100644 --- a/packages/fes-plugin-layout/src/node/helper.js +++ b/packages/fes-plugin-layout/src/node/helper.js @@ -39,9 +39,19 @@ export const fillMenuByRoute = (menuConfig, routeConfig, dep = 0) => { // 处理icon if (menu.icon) { const icon = menu.icon; - const iconName = `${icon.replace(icon[0], icon[0].toUpperCase())}Outlined`; - if (!allIcons[icon]) { - menu.icon = iconName; + const urlReg = /^((https?|ftp|file):\/\/)?([\da-z.-]+)\.([a-z.]{2,6})([/\w .-]*)*\/?$/; + if (!(urlReg.test(icon) || icon.includes('.svg'))) { + if (!allIcons[icon]) { + menu.icon = { + type: 'icon', + name: `${icon.replace(icon[0], icon[0].toUpperCase())}Outlined` + }; + } else { + menu.icon = { + type: 'icon', + name: icon + }; + } } } if (menu.children && menu.children.length > 0) { @@ -61,7 +71,9 @@ export function getIconsFromMenu(data) { (data || []).forEach((item = { path: '/' }) => { if (item.icon) { const { icon } = item; - icons.push(icon); + if (icon && icon.type === 'icon') { + icons.push(icon.name); + } } if (item.children) { icons = icons.concat(getIconsFromMenu(item.children)); diff --git a/packages/fes-plugin-layout/src/runtime/helpers/svg.js b/packages/fes-plugin-layout/src/runtime/helpers/svg.js new file mode 100644 index 00000000..f42d5cb5 --- /dev/null +++ b/packages/fes-plugin-layout/src/runtime/helpers/svg.js @@ -0,0 +1,49 @@ +const isStr = function (str) { + return typeof str === 'string'; +}; + +export const isValid = (elm) => { + if (elm.nodeType === 1) { + if (elm.nodeName.toLowerCase() === 'script') { + return false; + } + + for (let i = 0; i < elm.attributes.length; i++) { + const val = elm.attributes[i].value; + if (isStr(val) && val.toLowerCase().indexOf('on') === 0) { + return false; + } + } + + for (let i = 0; i < elm.childNodes.length; i++) { + if (!isValid(elm.childNodes[i])) { + return false; + } + } + } + return true; +}; + +export const validateContent = (svgContent) => { + const div = document.createElement('div'); + div.innerHTML = svgContent; + + // setup this way to ensure it works on our buddy IE + for (let i = div.childNodes.length - 1; i >= 0; i--) { + if (div.childNodes[i].nodeName.toLowerCase() !== 'svg') { + div.removeChild(div.childNodes[i]); + } + } + + // must only have 1 root element + const svgElm = div.firstElementChild; + if (svgElm && svgElm.nodeName.toLowerCase() === 'svg') { + // root element must be an svg + // lets double check we've got valid elements + // do not allow scripts + if (isValid(svgElm)) { + return div.innerHTML; + } + } + return ''; +}; diff --git a/packages/fes-plugin-layout/src/runtime/views/Menu.vue b/packages/fes-plugin-layout/src/runtime/views/Menu.vue index 264ae82a..ce330873 100644 --- a/packages/fes-plugin-layout/src/runtime/views/Menu.vue +++ b/packages/fes-plugin-layout/src/runtime/views/Menu.vue @@ -7,7 +7,7 @@ > @@ -47,7 +47,7 @@ + diff --git a/packages/fes-plugin-locale/src/runtime/core.tpl b/packages/fes-plugin-locale/src/runtime/core.tpl index 232acc8c..e6914861 100644 --- a/packages/fes-plugin-locale/src/runtime/core.tpl +++ b/packages/fes-plugin-locale/src/runtime/core.tpl @@ -12,7 +12,7 @@ import SelectLang from "./views/SelectLang"; {{ #SHARE }} // 共享出去 -plugin.share("locale", { SelectLang }); +plugin.share("locale", {useI18n, SelectLang }); {{ /SHARE }} const locales = {{{REPLACE_LOCALES}}}; diff --git a/packages/fes-template/.fes.js b/packages/fes-template/.fes.js index 8b1b4498..e0f64071 100644 --- a/packages/fes-template/.fes.js +++ b/packages/fes-template/.fes.js @@ -34,7 +34,7 @@ export default { navigation: 'mixin', menus: [{ name: 'index', - icon: 'user' + icon: '/wine-outline.svg' }, { name: 'onepiece', icon: 'user', diff --git a/packages/fes-template/public/wine-outline.svg b/packages/fes-template/public/wine-outline.svg new file mode 100644 index 00000000..cebc9931 --- /dev/null +++ b/packages/fes-template/public/wine-outline.svg @@ -0,0 +1 @@ +Wine \ No newline at end of file diff --git a/packages/fes-template/src/locales/en-US.js b/packages/fes-template/src/locales/en-US.js index 72836ca1..d2c8653c 100644 --- a/packages/fes-template/src/locales/en-US.js +++ b/packages/fes-template/src/locales/en-US.js @@ -1,6 +1,7 @@ export default { test: 'test', + home: 'home', 'navBar.lang': 'Languages', 'layout.user.link.help': 'Help', 'layout.user.link.privacy': 'Privacy', diff --git a/packages/fes-template/src/locales/zh-CN.js b/packages/fes-template/src/locales/zh-CN.js index a30cba5e..bbc8138d 100644 --- a/packages/fes-template/src/locales/zh-CN.js +++ b/packages/fes-template/src/locales/zh-CN.js @@ -1,6 +1,7 @@ export default { test: '测试', + home: '首页', 'navBar.lang': '语言', 'layout.user.link.help': '帮助', 'layout.user.link.privacy': '隐私', diff --git a/packages/fes-template/src/pages/index.vue b/packages/fes-template/src/pages/index.vue index 60e0cb58..9c709a0f 100644 --- a/packages/fes-template/src/pages/index.vue +++ b/packages/fes-template/src/pages/index.vue @@ -14,7 +14,7 @@ { "name": "index", - "title": "首页" + "title": "home" }