update: 优化ProLayout

This commit is contained in:
xieyonghong 2023-03-13 19:33:16 +08:00
parent 34d3ff7419
commit 3b04286842
6 changed files with 117 additions and 49 deletions

View File

@ -8,10 +8,13 @@
:breadcrumb="{ routes: breadcrumb }" :breadcrumb="{ routes: breadcrumb }"
> >
<template #breadcrumbRender="slotProps"> <template #breadcrumbRender="slotProps">
<a v-if="slotProps.route.index !== 0">{{ <a
slotProps.route.breadcrumbName v-if="slotProps.route.index !== 0 && !slotProps.route.isLast"
}}</a> @click='() => jumpPage(slotProps.route.path)'
<span v-else>{{ slotProps.route.breadcrumbName }}</span> >
{{ slotProps.route.breadcrumbName }}
</a>
<span v-else >{{ slotProps.route.breadcrumbName }}</span>
</template> </template>
<template #rightContentRender> <template #rightContentRender>
<div class="right-content"> <div class="right-content">
@ -32,6 +35,7 @@ import Notice from './components/Notice.vue';
import DefaultSetting from '../../../config/config'; import DefaultSetting from '../../../config/config';
import { useMenuStore } from '@/store/menu'; import { useMenuStore } from '@/store/menu';
import { clearMenuItem } from 'jetlinks-ui-components/es/ProLayout/util'; import { clearMenuItem } from 'jetlinks-ui-components/es/ProLayout/util';
import { AccountMenu } from '@/router/menu'
type StateType = { type StateType = {
collapsed: boolean; collapsed: boolean;
@ -50,7 +54,8 @@ const layoutConf = reactive({
siderWidth: DefaultSetting.layout.siderWidth, siderWidth: DefaultSetting.layout.siderWidth,
logo: DefaultSetting.layout.logo, logo: DefaultSetting.layout.logo,
title: DefaultSetting.layout.title, title: DefaultSetting.layout.title,
menuData: clearMenuItem(menu.siderMenus), menuData: [...clearMenuItem(menu.siderMenus), AccountMenu],
// menuData: menu.siderMenus,
splitMenus: true, splitMenus: true,
}); });
@ -61,26 +66,49 @@ const state = reactive<StateType>({
selectedKeys: [], selectedKeys: [],
}); });
const findRouteMeta = (code: string) => {
let meta = []
let menuItem: any = menu.menus[code]
while (menuItem) {
meta.unshift(menuItem)
if (menuItem.parentName) {
menuItem = menu.menus[menuItem.parentName]
} else {
menuItem = false
}
}
return meta
}
const jumpPage = (path: string) => {
console.log(path)
router.push(path)
}
const breadcrumb = computed(() => const breadcrumb = computed(() =>
router.currentRoute.value.matched.concat().map((item, index) => { {
return { const paths = router.currentRoute.value.name as string
index, const metas = findRouteMeta(paths)
path: item.path, return metas.map((item, index) => {
breadcrumbName: item.meta.title || '', return {
}; index,
}), isLast: index === (metas.length - 1),
path: item.path,
breadcrumbName: item.title || '',
};
})
}
); );
watchEffect(() => { watchEffect(() => {
if (router.currentRoute) { if (router.currentRoute) {
const matched = router.currentRoute.value.matched.concat(); const paths = router.currentRoute.value.name as string
state.selectedKeys = matched.map((r) => r.path); if (paths) {
state.openKeys = matched const _metas = findRouteMeta(paths)
.filter((r) => r.path !== router.currentRoute.value.path) state.selectedKeys = _metas.map(item => item.path)
.map((r) => r.path); state.openKeys = _metas.filter((r) => r !== router.currentRoute.value.path).map(item => item.path)
console.log(state.selectedKeys); }
} }
// TODO pure
}); });
watchEffect(() => { watchEffect(() => {

View File

@ -5,6 +5,7 @@ export const AccountMenu = {
component: () => import('@/components/Layout/BasicLayoutPage.vue'), component: () => import('@/components/Layout/BasicLayoutPage.vue'),
redirect: '/account/center', redirect: '/account/center',
name: 'account', name: 'account',
code: 'account',
meta: { meta: {
title: '个人中心', title: '个人中心',
icon: '', icon: '',
@ -14,6 +15,7 @@ export const AccountMenu = {
{ {
path: '/account/center', path: '/account/center',
name: 'account/center', name: 'account/center',
code: 'account/center',
meta: { meta: {
title: '基本设置', title: '基本设置',
icon: '', icon: '',
@ -24,6 +26,7 @@ export const AccountMenu = {
{ {
path: '/account/NotificationSubscription', path: '/account/NotificationSubscription',
name: 'account/NotificationSubscription', name: 'account/NotificationSubscription',
code: 'account/NotificationSubscription',
meta: { meta: {
title: '通知订阅', title: '通知订阅',
icon: '', icon: '',
@ -34,6 +37,7 @@ export const AccountMenu = {
{ {
path: '/account/NotificationRecord', path: '/account/NotificationRecord',
name: 'account/NotificationRecord', name: 'account/NotificationRecord',
code: 'account/NotificationRecord',
meta: { meta: {
title: '通知记录', title: '通知记录',
icon: '', icon: '',

View File

@ -1,6 +1,6 @@
import { defineStore } from 'pinia' import { defineStore } from 'pinia'
import { queryOwnThree } from '@/api/system/menu' import { queryOwnThree } from '@/api/system/menu'
import { filterAsnycRouter, MenuItem } from '@/utils/menu' import { filterAsyncRouter, findCodeRoute, MenuItem } from '@/utils/menu'
import { isArray } from 'lodash-es' import { isArray } from 'lodash-es'
import { usePermissionStore } from './permission' import { usePermissionStore } from './permission'
import router from '@/router' import router from '@/router'
@ -33,6 +33,8 @@ type MenuStateType = {
menus: { menus: {
[key: string]: { [key: string]: {
buttons?: string[] buttons?: string[]
title: string
parentName: string
path: string path: string
} }
} }
@ -98,24 +100,15 @@ export const useMenuStore = defineStore({
if (resp.success) { if (resp.success) {
const permission = usePermissionStore() const permission = usePermissionStore()
permission.permissions = {} permission.permissions = {}
const { menusData, silderMenus } = filterAsnycRouter(resp.result) const { menusData, silderMenus } = filterAsyncRouter(resp.result)
this.menus = {} this.menus = findCodeRoute([...resp.result, AccountMenu])
const handleMenuItem = (menu: any) => { Object.keys(this.menus).forEach((item) => {
if (isArray(menu)) { const _item = this.menus[item]
menu.forEach(menuItem => { if (_item.buttons?.length) {
this.menus[menuItem.name] = { permission.permissions[item] = _item.buttons
path: menuItem.path,
buttons: menuItem.meta.buttons
}
permission.permissions[menuItem.name] = menuItem.meta.buttons
if (menuItem.children && menuItem.children.length) {
handleMenuItem(menuItem.children)
}
})
} }
} })
handleMenuItem(menusData)
menusData.push({ menusData.push({
path: '/', path: '/',
redirect: menusData[0]?.path, redirect: menusData[0]?.path,
@ -124,10 +117,7 @@ export const useMenuStore = defineStore({
} }
}) })
menusData.push(AccountMenu) menusData.push(AccountMenu)
silderMenus.push(AccountMenu)
this.siderMenus = silderMenus this.siderMenus = silderMenus
console.log('menusData', menusData)
console.log('silderMenus', silderMenus)
res(menusData) res(menusData)
} }
}) })

View File

@ -3,11 +3,12 @@ import { defineStore } from "pinia";
export const usePermissionStore = defineStore({ export const usePermissionStore = defineStore({
id: 'permission', id: 'permission',
state: () => ({ state: () => ({
permissions: {} as {[key: string]: string}, permissions: {} as {[key: string]: string[]},
}), }),
getters: { getters: {
check(state) { check(state) {
return (permissionCode: string) => { return (permissionCode: string) => {
if (!permissionCode) { if (!permissionCode) {
return true return true
} }
@ -16,6 +17,7 @@ export const usePermissionStore = defineStore({
} }
const code = permissionCode.split(":")[0] const code = permissionCode.split(":")[0]
const value = permissionCode.split(":")[1] const value = permissionCode.split(":")[1]
const _buttonArray = state.permissions[code] const _buttonArray = state.permissions[code]
if (!_buttonArray) { if (!_buttonArray) {
return false return false

View File

@ -151,7 +151,6 @@ const extraRouteObj = {
const resolveComponent = (name: any) => { const resolveComponent = (name: any) => {
const importPage = pagesComponent[`../views/${name}/index.vue`]; const importPage = pagesComponent[`../views/${name}/index.vue`];
if (!importPage) { if (!importPage) {
console.warn(`Unknown page ${name}. Is it located under Pages with a .vue extension?`)
return undefined return undefined
} else { } else {
const res = () => importPage() const res = () => importPage()
@ -201,7 +200,52 @@ const findDetailRoutes = (routes: any[]): any[] => {
return newRoutes return newRoutes
} }
export function filterAsnycRouter(asyncRouterMap: any, parentCode = '', level = 1): { menusData: any, silderMenus: any } { export const findCodeRoute = (asyncRouterMap: any[]) => {
const routeMeta = {}
function findChildren (data: any[], code: string = '') {
data.forEach(route => {
routeMeta[route.code] = {
path: route.url || route.path,
title: route.meta?.title || route.name,
parentName: code,
buttons: route.buttons?.map((b: any) => b.id) || []
}
const detail = findDetailRouteItem(route.code, route.url)
if (detail) {
routeMeta[(detail as MenuItem).code] = {
path: detail.url,
title: detail.name,
parentName: route.code,
buttons: detail.buttons?.map((b: any) => b.id) || []
}
}
const otherRoutes = extraRouteObj[route.code]
if (otherRoutes) {
otherRoutes.children.map((item: any) => {
const _code = `${route.code}/${item.code}`
routeMeta[_code] = {
path: `${route.url}/${item.code}`,
title: item.name,
parentName: route.code,
buttons: item.buttons?.map((b: any) => b.id) || []
}
})
}
if (route.children) {
findChildren(route.children, route.code)
}
})
}
findChildren(asyncRouterMap)
return routeMeta
}
export function filterAsyncRouter(asyncRouterMap: any, parentCode = '', level = 1): { menusData: any, silderMenus: any} {
const _asyncRouterMap = cloneDeep(asyncRouterMap) const _asyncRouterMap = cloneDeep(asyncRouterMap)
const menusData: any[] = [] const menusData: any[] = []
const silderMenus: any[] = [] const silderMenus: any[] = []
@ -224,7 +268,7 @@ export function filterAsnycRouter(asyncRouterMap: any, parentCode = '', level =
route.children = findDetailRoutes(route.children) route.children = findDetailRoutes(route.children)
if (route.children && route.children.length) { if (route.children && route.children.length) {
// TODO 查看是否具有详情页 // TODO 查看是否具有详情页
const { menusData: _menusData, silderMenus: _silderMenus } = filterAsnycRouter(route.children, `${parentCode}/${route.code}`, level + 1) const { menusData: _menusData, silderMenus: _silderMenus } = filterAsyncRouter(route.children, `${parentCode}/${route.code}`, level + 1)
_route.children = _menusData _route.children = _menusData
silder.children = _silderMenus silder.children = _silderMenus
const showChildren = _route.children.some((r: any) => !r.meta.hideInMenu) const showChildren = _route.children.some((r: any) => !r.meta.hideInMenu)
@ -251,6 +295,6 @@ export function filterAsnycRouter(asyncRouterMap: any, parentCode = '', level =
}) })
return { return {
menusData, menusData,
silderMenus silderMenus,
} }
} }

View File

@ -95,6 +95,7 @@ import { queryFlow, list } from '@/api/iot-card/home';
import * as echarts from 'echarts'; import * as echarts from 'echarts';
import { useMenuStore } from '@/store/menu'; import { useMenuStore } from '@/store/menu';
import { usePermissionStore } from '@/store/permission'; import { usePermissionStore } from '@/store/permission';
import { message } from 'jetlinks-ui-components'
const { proxy } = <any>getCurrentInstance(); const { proxy } = <any>getCurrentInstance();
@ -178,11 +179,10 @@ const pieChartData = ref<any[]>([
]); ]);
const jumpPage = (data: GuideItemProps) => { const jumpPage = (data: GuideItemProps) => {
// if (data.url && data.auth) { if (!data.auth){
// router.push({ path: `${data.url}`, ...data.param }); message.warning('暂无权限,请联系管理员');
// } else { return
// message.warning(''); }
// }
if (data.key === 'EQUIPMENT') { if (data.key === 'EQUIPMENT') {
menuStory.jumpPage(data.url, { id: 'add' }); menuStory.jumpPage(data.url, { id: 'add' });
} else { } else {