Commit 58e30151 authored by 陈浩玮's avatar 陈浩玮

Merge branch 'feature/shuiluo' into 'master'

feat: 菜单权限代码处理

See merge request product/kim3-web-vue/starter-web-vue!28
parents ed54b020 445c4639
......@@ -66,9 +66,7 @@ export default {
},
setHtmlTitle() {
const route = this.$route;
const key =
route.path === '/' ? 'home.name' : getI18nKey(route.matched[route.matched.length - 1].path);
document.title = process.env.VUE_APP_NAME + ' | ' + this.$t(key);
if (route.name) window.title = route.name;
},
popContainer() {
return document.getElementById('popContainer');
......
<template>
<a-layout-sider :theme="sideTheme" :class="['side-menu', 'beauty-scroll', isMobile ? null : 'shadow']" width="256px" :collapsible="collapsible" v-model="collapsed" :trigger="null">
<a-layout-sider
:theme="sideTheme"
:class="['side-menu', 'beauty-scroll', isMobile ? null : 'shadow']"
width="256px"
:collapsible="collapsible"
v-model="collapsed"
:trigger="null"
>
<div :class="['logo', theme]">
<router-link to="/dashboard/workplace">
<img src="@/assets/img/logo.png">
<h1>{{systemName}}</h1>
<img src="@/assets/img/logo.png" />
<h1>{{ systemName }}</h1>
</router-link>
</div>
<i-menu :theme="theme" :collapsed="collapsed" :options="menuData" @select="onSelect" class="menu" />
......@@ -13,6 +20,7 @@
<script>
import IMenu from './menu';
import { mapState } from 'vuex';
export default {
name: 'SideMenu',
components: { IMenu },
......
......@@ -31,15 +31,14 @@
* }
* }
**/
import Menu from "ant-design-vue/es/menu";
import Icon from "ant-design-vue/es/icon";
import fastEqual from "fast-deep-equal";
import {getI18nKey} from '@/utils/routerUtil'
import Menu from 'ant-design-vue/es/menu';
import Icon from 'ant-design-vue/es/icon';
import { getUserInfo } from '@/utils';
const { Item, SubMenu } = Menu;
export default {
name: "IMenu",
name: 'IMenu',
props: {
options: {
type: Array,
......@@ -48,12 +47,12 @@ export default {
theme: {
type: String,
required: false,
default: "dark",
default: 'dark',
},
mode: {
type: String,
required: false,
default: "inline",
default: 'inline',
},
collapsed: {
type: Boolean,
......@@ -61,43 +60,37 @@ export default {
default: false,
},
i18n: Object,
openKeys: Array,
},
data() {
return {
selectedKeys: [],
sOpenKeys: [],
cachedOpenKeys: [],
menuData: [],
};
},
computed: {
menuTheme() {
return this.theme == "light" ? this.theme : "dark";
return this.theme == 'light' ? this.theme : 'dark';
},
},
created() {
const { menuList } = getUserInfo();
this.menuData = menuList.filter(i => i.menuType === 'MENU');
this.updateMenu();
if (this.options.length > 0 && !this.options[0].fullPath) {
this.formatOptions(this.options, "");
}
// 自定义国际化配置
if (this.i18n && this.i18n.messages) {
const messages = this.i18n.messages;
Object.keys(messages).forEach((key) => {
this.$i18n.mergeLocaleMessage(key, messages[key]);
});
}
// // 自定义国际化配置
// if (this.i18n && this.i18n.messages) {
// const messages = this.i18n.messages;
// Object.keys(messages).forEach(key => {
// this.$i18n.mergeLocaleMessage(key, messages[key]);
// });
// }
},
watch: {
options(val) {
if (val.length > 0 && !val[0].fullPath) {
this.formatOptions(this.options, "");
}
},
i18n(val) {
if (val && val.messages) {
const messages = this.i18n.messages;
Object.keys(messages).forEach((key) => {
Object.keys(messages).forEach(key => {
this.$i18n.mergeLocaleMessage(key, messages[key]);
});
}
......@@ -114,112 +107,97 @@ export default {
this.updateMenu();
},
sOpenKeys(val) {
this.$emit("openChange", val);
this.$emit("update:openKeys", val);
this.$emit('openChange', val);
this.$emit('update:openKeys', val);
},
},
methods: {
renderIcon: function(h, icon, key) {
if (this.$scopedSlots.icon && icon && icon !== "none") {
renderIcon(h, icon, key) {
if (this.$scopedSlots.icon && icon && icon !== 'none') {
const vnodes = this.$scopedSlots.icon({ icon, key });
vnodes.forEach((vnode) => {
vnodes.forEach(vnode => {
vnode.data.class = vnode.data.class ? vnode.data.class : [];
vnode.data.class.push("anticon");
vnode.data.class.push('anticon');
});
return vnodes;
}
return !icon || icon == "none" ? null : h(Icon, { props: { type: icon } });
return !icon || icon == 'none' ? null : h(Icon, { props: { type: icon } });
},
renderMenuItem: function(h, menu) {
let tag = "router-link";
let config = {
props: { to: menu.fullPath },
attrs: { style: "overflow:hidden;white-space:normal;text-overflow:clip;" },
renderMenuItem(h, menu) {
const tag = 'router-link';
const config = {
props: { to: menu.path },
attrs: { style: 'overflow:hidden;white-space:normal;text-overflow:clip;' },
};
if (menu.meta && menu.meta.link) {
tag = "a";
config = {
attrs: {
style: "overflow:hidden;white-space:normal;text-overflow:clip;",
href: menu.meta.link,
target: "_blank",
},
};
}
return h(Item, { key: menu.fullPath }, [
h(tag, config, [
this.renderIcon(h, menu.meta ? menu.meta.icon : "none", menu.fullPath),
this.$t(getI18nKey(menu.fullPath)),
]),
return h(Item, { key: menu.menuId }, [
h(tag, config, [this.renderIcon(h, menu.menuIcon, menu.menuId), menu.menuName]),
]);
},
renderSubMenu: function(h, menu) {
let this_ = this;
let subItem = [
renderSubMenu(h, menu) {
const subItem = [
h(
"span",
{ slot: "title", attrs: { style: "overflow:hidden;white-space:normal;text-overflow:clip;" } },
[
this.renderIcon(h, menu.meta ? menu.meta.icon : "none", menu.fullPath),
this.$t(getI18nKey(menu.fullPath)),
]
'span',
{
slot: 'title',
attrs: { style: 'overflow:hidden;white-space:normal;text-overflow:clip;' },
},
[this.renderIcon(h, menu.menuIcon, menu.menuId), menu.menuName],
),
];
let itemArr = [];
menu.children.forEach(function(item) {
itemArr.push(this_.renderItem(h, item));
const itemArr = [];
menu.children.forEach(item => {
itemArr.push(this.renderItem(h, item));
});
return h(SubMenu, { key: menu.fullPath }, subItem.concat(itemArr));
},
renderItem: function(h, menu) {
const meta = menu.meta;
if (!meta || !meta.invisible) {
let renderChildren = false;
const children = menu.children;
if (children != undefined) {
for (let i = 0; i < children.length; i++) {
const childMeta = children[i].meta;
if (!childMeta || !childMeta.invisible) {
renderChildren = true;
break;
}
}
}
return menu.children && renderChildren ? this.renderSubMenu(h, menu) : this.renderMenuItem(h, menu);
}
return h(SubMenu, { key: menu.menuId }, subItem.concat(itemArr));
},
renderMenu: function(h, menuTree) {
let this_ = this;
renderItem(h, menu) {
return menu.children && menu.children.length
? this.renderSubMenu(h, menu)
: this.renderMenuItem(h, menu);
},
renderMenu(h, menuTree) {
let menuArr = [];
menuTree.forEach(function(menu, i) {
menuArr.push(this_.renderItem(h, menu, "0", i));
menuTree.forEach((menu, i) => {
menuArr.push(this.renderItem(h, menu));
});
return menuArr;
},
formatOptions(options, parentPath) {
options.forEach((route) => {
let isFullPath = route.path.substring(0, 1) == "/";
route.fullPath = isFullPath ? route.path : parentPath + "/" + route.path;
if (route.children) {
this.formatOptions(route.children, route.fullPath);
}
});
},
updateMenu() {
const matchedRoutes = this.$route.matched.filter((item) => item.path !== "");
this.selectedKeys = this.getSelectedKey(this.$route);
let openKeys = matchedRoutes.map((item) => item.path);
openKeys = openKeys.slice(0, openKeys.length - 1);
if (!fastEqual(openKeys, this.sOpenKeys)) {
this.collapsed || this.mode === "horizontal"
? (this.cachedOpenKeys = openKeys)
: (this.sOpenKeys = openKeys);
}
// let openKeys = matchedRoutes.map(item => item.path);
// openKeys = openKeys.slice(0, openKeys.length - 1);
// if (!fastEqual(openKeys, this.sOpenKeys)) {
// this.collapsed || this.mode === 'horizontal'
// ? (this.cachedOpenKeys = openKeys)
// : (this.sOpenKeys = openKeys);
// }
this.sOpenKeys = this.getOpenKeysByPath(this.$route.path);
},
getSelectedKey(route) {
return route.matched.map((item) => item.path);
const { path } = route;
return [this.menuData.find(m => m.menuUrl === path).menuId];
},
getOpenKeysByPath(path) {
const { menuList } = getUserInfo();
const { parentMenuId } = this.menuData.find(m => m.menuUrl === path);
if (parentMenuId === 0) return [];
const parentMenus = [parentMenuId];
const res = [parentMenuId];
while (parentMenus.length) {
const menuId = parentMenus.pop();
const parentMenu = menuList.find(m => m.menuId === menuId);
if (parentMenu.parentMenuId !== 0) {
parentMenus.push(parentMenu.parentMenuId);
res.push(parentMenu.parentMenuId);
}
}
return res;
},
},
render(h) {
......@@ -230,19 +208,19 @@ export default {
theme: this.menuTheme,
mode: this.$props.mode,
selectedKeys: this.selectedKeys,
openKeys: this.openKeys ? this.openKeys : this.sOpenKeys,
openKeys: this.sOpenKeys,
},
on: {
"update:openKeys": (val) => {
'update:openKeys': val => {
this.sOpenKeys = val;
},
click: (obj) => {
click: obj => {
obj.selectedKeys = [obj.key];
this.$emit("select", obj);
this.$emit('select', obj);
},
},
},
this.renderMenu(h, this.options)
this.renderMenu(h, this.options),
);
},
};
......@@ -23,7 +23,7 @@
v-if="fixedSideBar && !isMobile"
:style="`width: ${sideMenuWidth}; min-width: ${sideMenuWidth};max-width: ${sideMenuWidth};`"
class="virtual-side"
></div>
/>
<drawer v-if="!hideSettingExtend" v-model="showSetting" placement="right">
<div class="setting" slot="handler">
......@@ -59,9 +59,10 @@
<script>
import LayoutTopHeader from '../components/header/LayoutTopHeader';
import Drawer from '@/components/tool/Drawer';
import SideMenu from '@/components/menu/SideMenu';
import SideMenu from '@/components/menu/SideMenu.vue';
import Setting from '../components/setting/Setting';
import { mapState, mapMutations, mapGetters } from 'vuex';
import { convertListToTree, getUserInfo } from '@/utils';
// const minHeight = window.innerHeight - 64 - 122
......@@ -74,6 +75,7 @@ export default {
collapsed: false,
showSetting: false,
drawerOpen: false,
menuData: [],
};
},
provide() {
......@@ -108,7 +110,7 @@ export default {
'multiPage',
]),
...mapGetters('settingModule', ['firstMenu', 'subMenu', 'menuData']),
...mapGetters('settingModule', ['firstMenu', 'subMenu']),
hideSettingExtend() {
if (this.hideSetting === false && process.env.NODE_ENV === 'development') {
......@@ -161,6 +163,9 @@ export default {
created() {
this.correctPageMinHeight(this.minHeight - 24);
this.setActivated(this.$route);
const userInfo = getUserInfo();
const menuData = convertListToTree(userInfo?.menuList || [], false, true);
this.menuData = menuData;
},
beforeDestroy() {
this.correctPageMinHeight(-this.minHeight + 24);
......
......@@ -34,12 +34,16 @@ export function clearUserInfo() {
* @param {Array} menuList 菜单列表
* @param {Boolean} filterMenu 是否过滤掉菜单,只保留目录
*/
export function convertListToTree(menuList, filterMenu = false) {
export function convertListToTree(menuList, filterMenu = false, toMenuData = false) {
let tempMenu = [...menuList];
if (filterMenu) {
tempMenu = tempMenu.filter(m => m.menuType !== 'MENU');
}
for (const menu of menuList) {
if (toMenuData) {
menu.name = menu.menuName;
menu.path = menu.menuUrl;
}
if (menu.parentMenuId === 0) continue;
const parent = menuList.find(m => m.menuId === menu.parentMenuId);
parent.children ? parent.children.push(menu) : (parent.children = [menu]);
......
......@@ -78,18 +78,16 @@ function loadRoutes(routesConfig) {
// 应用配置
const { router, store, i18n } = appOptions;
// 如果 routesConfig 有值,则更新到本地,否则从本地获取
if (routesConfig) {
store.commit('accountModule/setRoutesConfig', routesConfig);
} else {
routesConfig = store.getters['accountModule/routesConfig'];
}
// 提取路由国际化数据
mergeI18nFromRoutes(i18n, router.options.routes);
// 初始化Admin后台菜单数据
const rootRoute = router.options.routes.find(item => item.path === '/');
const menuRoutes = rootRoute && rootRoute.children;
if (menuRoutes) {
store.commit('settingModule/setMenuData', menuRoutes);
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment