fix: 优化菜单跳转
This commit is contained in:
parent
77dc3347a8
commit
d9f67af30b
|
@ -1,10 +1,5 @@
|
|||
<template>
|
||||
<ConfigProvider :locale='zhCN'>
|
||||
<!-- <router-view v-slot="{ Component }">-->
|
||||
<!-- <keep-alive>-->
|
||||
<!-- <component :is="Component" />-->
|
||||
<!-- </keep-alive>-->
|
||||
<!-- </router-view>-->
|
||||
<router-view />
|
||||
</ConfigProvider>
|
||||
</template>
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
<template>
|
||||
<j-pro-layout
|
||||
v-bind="layoutConf"
|
||||
v-model:openKeys="state.openKeys"
|
||||
v-model:collapsed="state.collapsed"
|
||||
v-model:selectedKeys="state.selectedKeys"
|
||||
v-model:collapsed="basicLayout.collapsed"
|
||||
v-model:openKeys="basicLayout.openKeys"
|
||||
v-model:selectedKeys="basicLayout.selectedKeys"
|
||||
:headerHeight='layout.headerHeight'
|
||||
:pure="state.pure"
|
||||
:breadcrumb="{ routes: breadcrumb }"
|
||||
:breadcrumb="{ routes: breadcrumbs }"
|
||||
:pure="basicLayout.pure"
|
||||
@backClick='routerBack'
|
||||
>
|
||||
<template #breadcrumbRender="slotProps">
|
||||
|
@ -25,9 +25,9 @@
|
|||
<UserInfo />
|
||||
</div>
|
||||
</template>
|
||||
<router-view v-slot="{ Component }">
|
||||
<component :is="Component" />
|
||||
</router-view>
|
||||
<router-view v-slot="{ Component }">
|
||||
<component :is="components || Component" />
|
||||
</router-view>
|
||||
</j-pro-layout>
|
||||
</template>
|
||||
|
||||
|
@ -54,14 +54,14 @@ const route = useRoute();
|
|||
const menu = useMenuStore();
|
||||
|
||||
const system = useSystem();
|
||||
const {configInfo,layout} = storeToRefs(system);
|
||||
const {configInfo,layout, basicLayout} = storeToRefs(system);
|
||||
|
||||
const layoutConf = reactive({
|
||||
theme: DefaultSetting.layout.theme,
|
||||
siderWidth: layout.value.siderWidth,
|
||||
logo: DefaultSetting.layout.logo,
|
||||
title: DefaultSetting.layout.title,
|
||||
menuData: [...clearMenuItem(menu.siderMenus), AccountMenu],
|
||||
menuData: [...menu.siderMenus, AccountMenu],
|
||||
// menuData: menu.siderMenus,
|
||||
splitMenus: true,
|
||||
});
|
||||
|
@ -72,87 +72,51 @@ watchEffect(() => {
|
|||
layoutConf.logo = configInfo.value.front?.logo || DefaultSetting.layout.logo;
|
||||
})
|
||||
|
||||
const state = reactive<StateType>({
|
||||
pure: false,
|
||||
collapsed: false, // default value
|
||||
openKeys: [],
|
||||
selectedKeys: [],
|
||||
});
|
||||
const components = computed(() => {
|
||||
const componentName = route.matched[route.matched.length - 1]?.components?.default?.name
|
||||
if (componentName !== 'BasicLayoutPage') {
|
||||
return route.matched[route.matched.length - 1]?.components?.default
|
||||
}
|
||||
return undefined
|
||||
})
|
||||
|
||||
/**
|
||||
* 面包屑
|
||||
*/
|
||||
const breadcrumbs = computed(() =>
|
||||
{
|
||||
const paths = router.currentRoute.value.matched
|
||||
|
||||
return paths.map((item, index) => {
|
||||
return {
|
||||
index,
|
||||
isLast: index === (paths.length -1),
|
||||
path: item.path,
|
||||
breadcrumbName: (item.meta as any).title || '',
|
||||
}
|
||||
})
|
||||
}
|
||||
);
|
||||
|
||||
const routerBack = () => {
|
||||
router.go(-1)
|
||||
}
|
||||
|
||||
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 jump = (item: any) => {
|
||||
let path = history.state.back
|
||||
if (path) {
|
||||
// 包含query参数,清除?参数
|
||||
if (path.includes('?')) {
|
||||
const _path = path.split('?')[0]
|
||||
path = _path === item.path ? path : item.path
|
||||
} else if (path !== item.path) {
|
||||
path = item.path
|
||||
}
|
||||
} else {
|
||||
path = item.path
|
||||
}
|
||||
|
||||
// jumpPage(slotProps.route.path)
|
||||
router.push(path)
|
||||
router.push(item.path)
|
||||
}
|
||||
|
||||
const breadcrumb = computed(() =>
|
||||
{
|
||||
const paths = router.currentRoute.value.name as string
|
||||
|
||||
const metas = findRouteMeta(paths)
|
||||
return metas.map((item, index) => {
|
||||
return {
|
||||
index,
|
||||
isLast: index === (metas.length - 1),
|
||||
path: item.path,
|
||||
breadcrumbName: item.title || '',
|
||||
};
|
||||
})
|
||||
|
||||
watchEffect(() => {
|
||||
if (router.currentRoute) {
|
||||
const paths = router.currentRoute.value.matched
|
||||
basicLayout.value.selectedKeys = paths.map(item => item.path)
|
||||
basicLayout.value.openKeys = paths.map(item => item.path)
|
||||
console.log(paths) //
|
||||
}
|
||||
);
|
||||
|
||||
watchEffect(() => {
|
||||
if (router.currentRoute) {
|
||||
const paths = router.currentRoute.value.name as string
|
||||
if (paths) {
|
||||
const _metas = findRouteMeta(paths)
|
||||
state.selectedKeys = _metas.map(item => item.path)
|
||||
state.openKeys = _metas.filter((r) => r !== router.currentRoute.value.path).map(item => item.path)
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
watchEffect(() => {
|
||||
if (
|
||||
route.query &&
|
||||
'layout' in route.query &&
|
||||
route.query.layout === 'false'
|
||||
) {
|
||||
state.pure = true;
|
||||
} else {
|
||||
state.pure = false;
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
const toDoc = () => window.open('http://doc.v2.jetlinks.cn/');
|
||||
</script>
|
||||
|
|
|
@ -1,11 +1,21 @@
|
|||
<template>
|
||||
<router-view />
|
||||
<router-view v-slot="Component">
|
||||
<component :is="components || Component" />
|
||||
</router-view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'BlankLayoutPage'
|
||||
}
|
||||
<script name="BlankLayoutPage" setup>
|
||||
|
||||
const route = useRoute()
|
||||
|
||||
const components = computed(() => {
|
||||
const componentName = route.matched[route.matched.length - 1]?.components?.default?.name
|
||||
if (componentName !== 'BlankLayoutPage') {
|
||||
return route.matched[route.matched.length - 1]?.components?.default
|
||||
}
|
||||
return undefined
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
import { defineStore } from 'pinia'
|
||||
import { queryOwnThree } from '@/api/system/menu'
|
||||
import {filterAsyncRouter, filterCommunityMenus, findCodeRoute, MenuItem} from '@/utils/menu'
|
||||
import {
|
||||
handleMenus,
|
||||
MenuItem,
|
||||
handleSiderMenu,
|
||||
getAsyncRoutesMap, handleMenusMap
|
||||
} from '@/utils/menu'
|
||||
import { cloneDeep, isArray } from 'lodash-es'
|
||||
import { usePermissionStore } from './permission'
|
||||
import router from '@/router'
|
||||
|
@ -32,14 +37,7 @@ const defaultOwnParams = [
|
|||
]
|
||||
|
||||
type MenuStateType = {
|
||||
menus: {
|
||||
[key: string]: {
|
||||
buttons?: string[]
|
||||
title: string
|
||||
parentName: string
|
||||
path: string
|
||||
}
|
||||
}
|
||||
menus: any
|
||||
siderMenus: MenuItem[]
|
||||
params: Record<string, any>
|
||||
}
|
||||
|
@ -96,6 +94,10 @@ export const useMenuStore = defineStore({
|
|||
name, params, query, state: { params }
|
||||
})
|
||||
},
|
||||
handleMenusMapById(item: { code: string, path: string}) {
|
||||
const { name, path } = item
|
||||
this.menus[name] = {path}
|
||||
},
|
||||
queryMenuTree(isCommunity = false): Promise<any[]> {
|
||||
return new Promise(async (res) => {
|
||||
//过滤非集成的菜单
|
||||
|
@ -106,18 +108,12 @@ export const useMenuStore = defineStore({
|
|||
// if (!isNoCommunity) {
|
||||
// resultData = filterCommunityMenus(resultData)
|
||||
// }
|
||||
permission.permissions = {}
|
||||
const { menusData, silderMenus } = filterAsyncRouter(resultData)
|
||||
|
||||
|
||||
this.menus = findCodeRoute([...resultData]) // AccountMenu
|
||||
Object.keys(this.menus).forEach((item) => {
|
||||
const _item = this.menus[item]
|
||||
if (_item.buttons?.length) {
|
||||
permission.permissions[item] = _item.buttons
|
||||
}
|
||||
})
|
||||
|
||||
const components = getAsyncRoutesMap()
|
||||
const menusData = handleMenus(cloneDeep(resultData), components)
|
||||
permission.handlePermission(resultData)
|
||||
const silderMenus = handleSiderMenu(cloneDeep(resultData))
|
||||
// const { menusData, silderMenus } = filterAsyncRouter(resultData)
|
||||
handleMenusMap(cloneDeep(menusData), this.handleMenusMapById)
|
||||
menusData.push({
|
||||
path: '/',
|
||||
redirect: menusData[0]?.path,
|
||||
|
@ -125,6 +121,7 @@ export const useMenuStore = defineStore({
|
|||
hideInMenu: true
|
||||
}
|
||||
})
|
||||
// console.log(menusData)
|
||||
// menusData.push(AccountMenu)
|
||||
this.siderMenus = silderMenus.filter((item: { name: string }) => ![USER_CENTER_MENU_CODE, NotificationRecordCode, NotificationSubscriptionCode].includes(item.name))
|
||||
res(menusData)
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { defineStore } from "pinia";
|
||||
import {handleAuthMenu} from "@/utils/menu";
|
||||
|
||||
export const usePermissionStore = defineStore({
|
||||
id: 'permission',
|
||||
|
@ -39,5 +40,17 @@ export const usePermissionStore = defineStore({
|
|||
return false
|
||||
}
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
setPermission(code: string, buttons: string[]) {
|
||||
this.permissions[code] = buttons
|
||||
},
|
||||
cleanPermission() {
|
||||
this.permissions = {}
|
||||
},
|
||||
handlePermission(data: any) {
|
||||
this.cleanPermission()
|
||||
handleAuthMenu(data, this.setPermission)
|
||||
}
|
||||
}
|
||||
})
|
|
@ -13,6 +13,12 @@ type SystemStateType = {
|
|||
siderWidth: string | number | undefined; // 左侧菜单栏宽度
|
||||
headerHeight: string | number | undefined; // 头部高度
|
||||
collapsedWidth: string | number | undefined;
|
||||
},
|
||||
basicLayout: {
|
||||
selectedKeys: string[],
|
||||
openKeys: string[],
|
||||
collapsed: boolean
|
||||
pure: boolean
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -25,6 +31,12 @@ export const useSystem = defineStore('system', {
|
|||
siderWidth: 208, // 左侧菜单栏宽度
|
||||
headerHeight: 60, // 头部高度
|
||||
collapsedWidth: 48,
|
||||
},
|
||||
basicLayout: {
|
||||
selectedKeys: [],
|
||||
openKeys: [],
|
||||
collapsed: false,
|
||||
pure: false
|
||||
}
|
||||
}),
|
||||
actions: {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { cloneDeep } from 'lodash-es'
|
||||
import { BlankLayoutPage, BasicLayoutPage } from 'components/Layout'
|
||||
import { isNoCommunity } from '@/utils/utils'
|
||||
import Iframe from '../views/iframe/index.vue'
|
||||
|
||||
const pagesComponent = import.meta.glob('../views/**/*.vue');
|
||||
|
||||
|
@ -155,185 +155,363 @@ const extraRouteObj = {
|
|||
}
|
||||
};
|
||||
|
||||
//
|
||||
// const resolveComponent = (name: any) => {
|
||||
// const importPage = pagesComponent[`../views/${name}/index.vue`];
|
||||
// console.log(importPage)
|
||||
// if (!importPage) {
|
||||
// return undefined
|
||||
// } else {
|
||||
// const res = () => importPage()
|
||||
// return res
|
||||
// }
|
||||
// //@ts-ignore
|
||||
// }
|
||||
//
|
||||
// const findChildrenRoute = (code: string, url: string, routes: any[] = []): MenuItem[] => {
|
||||
// if (extraRouteObj[code]) {
|
||||
// const extraRoutes = extraRouteObj[code].children.map((route: MenuItem) => {
|
||||
// return {
|
||||
// url: `${url}/${route.code}`,
|
||||
// code: `${code}/${route.code}`,
|
||||
// name: route.name,
|
||||
// isShow: false
|
||||
// }
|
||||
// })
|
||||
// return [...routes, ...extraRoutes]
|
||||
// }
|
||||
// return routes
|
||||
// }
|
||||
//
|
||||
// const findDetailRouteItem = (code: string, url: string): Partial<MenuItem> | null => {
|
||||
// const detailComponent = resolveComponent(`${code}/Detail`)
|
||||
// if (detailComponent) {
|
||||
// return {
|
||||
// url: `${url}/detail/:id`,
|
||||
// code: `${code}/Detail`,
|
||||
// component: detailComponent,
|
||||
// name: '详情信息',
|
||||
// isShow: false
|
||||
// }
|
||||
// }
|
||||
// return null
|
||||
// }
|
||||
//
|
||||
// const findDetailRoutes = (routes: any[]): any[] => {
|
||||
// const newRoutes: any[] = []
|
||||
// routes.forEach((route: any) => {
|
||||
// newRoutes.push(route)
|
||||
// const detail = findDetailRouteItem(route.code, route.url)
|
||||
// if (detail) {
|
||||
// newRoutes.push(detail)
|
||||
// }
|
||||
// })
|
||||
// return newRoutes
|
||||
// }
|
||||
//
|
||||
// const filterMenus = ['device/DashBoard']
|
||||
// export const filterCommunityMenus = (menuData: any[]) => {
|
||||
// return menuData.filter(item => {
|
||||
// if (item.children) {
|
||||
// item.children = filterCommunityMenus(item.children)
|
||||
// }
|
||||
// return !filterMenus.includes(item.code)
|
||||
// })
|
||||
// }
|
||||
//
|
||||
// export const findCodeRoute = (asyncRouterMap: any[]) => {
|
||||
// const routeMeta = {}
|
||||
//
|
||||
// function getDetail(code: string, url: string) {
|
||||
// const detail = findDetailRouteItem(code, url)
|
||||
// if (!detail) return
|
||||
//
|
||||
// routeMeta[(detail as MenuItem).code] = {
|
||||
// path: detail.url,
|
||||
// title: detail.name,
|
||||
// parentName: code,
|
||||
// buttons: detail.buttons?.map((b: any) => b.id) || []
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// 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 otherRoutes = extraRouteObj[route.code]
|
||||
//
|
||||
// if (otherRoutes) {
|
||||
// otherRoutes.children.map((item: any) => {
|
||||
// const _code = `${route.code}/${item.code}`
|
||||
// const url = `${route.url}/${item.code}`
|
||||
// routeMeta[_code] = {
|
||||
// path: `${route.url}/${item.code}`,
|
||||
// title: item.name,
|
||||
// parentName: route.code,
|
||||
// buttons: item.buttons?.map((b: any) => b.id) || []
|
||||
// }
|
||||
// getDetail(_code, url)
|
||||
// })
|
||||
// }
|
||||
// const _code = route.appId ? `/${route.appId}${route.url}` : route.code
|
||||
// if (!route.appId) {
|
||||
// getDetail(_code, route.url)
|
||||
// } else {
|
||||
// routeMeta[_code] = {
|
||||
// path: `/${route.appId}${route.url}`,
|
||||
// title: route.name,
|
||||
// parentName: code,
|
||||
// buttons: []
|
||||
// }
|
||||
// }
|
||||
// if (route.children) {
|
||||
// findChildren(route.children, _code)
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
//
|
||||
// findChildren(asyncRouterMap)
|
||||
//
|
||||
// return routeMeta
|
||||
// }
|
||||
//
|
||||
// export function filterAsyncRouter(asyncRouterMap: any, parentCode = '', level = 1): { menusData: any, silderMenus: any } {
|
||||
// const _asyncRouterMap = cloneDeep(asyncRouterMap)
|
||||
// const menusData: any[] = []
|
||||
// const silderMenus: any[] = []
|
||||
// _asyncRouterMap.forEach((route: any) => {
|
||||
// const hasAppId = route.appId
|
||||
// const _route: any = {
|
||||
// path: hasAppId ? `/${route.appId}${route.url}` : `${route.url}`,
|
||||
// name: hasAppId ? `/${route.appId}${route.url}` : route.code,
|
||||
// url: hasAppId ? `/${route.appId}${route.url}` : route.url,
|
||||
// meta: {
|
||||
// icon: route.icon,
|
||||
// title: route.name,
|
||||
// hideInMenu: route.isShow === false,
|
||||
// buttons: route.buttons?.map((b: any) => b.id) || [],
|
||||
// isApp: hasAppId,
|
||||
// },
|
||||
// }
|
||||
//
|
||||
// const silder = { ..._route }
|
||||
// // 查看是否有隐藏子路由
|
||||
// route.children = findChildrenRoute(route.code, route.url, route.children)
|
||||
// route.children = findDetailRoutes(route.children)
|
||||
// if (route.children && route.children.length) {
|
||||
// // TODO 查看是否具有详情页
|
||||
// const { menusData: _menusData, silderMenus: _silderMenus } = filterAsyncRouter(route.children, `${parentCode}/${route.code}`, level + 1)
|
||||
// _route.children = _menusData
|
||||
// silder.children = _silderMenus
|
||||
// const showChildren = _route.children.some((r: any) => !r.meta.hideInMenu)
|
||||
//
|
||||
// if (showChildren && _route.children.length) {
|
||||
// _route.component = level === 1 ? BasicLayoutPage : BlankLayoutPage
|
||||
// _route.redirect = _route.children[0].url
|
||||
// } else {
|
||||
// const myComponent = resolveComponent(route.code)
|
||||
// // _route.component = myComponent ? myComponent : BlankLayoutPage;
|
||||
// if (!!myComponent) {
|
||||
// _route.component = myComponent;
|
||||
// _route.children.map((r: any) => menusData.push(r))
|
||||
// delete _route.children
|
||||
// } else {
|
||||
// _route.component = BlankLayoutPage
|
||||
// }
|
||||
// }
|
||||
// } else {
|
||||
// if (hasAppId) {
|
||||
// _route.component = route.component || resolveComponent('iframe')
|
||||
// } else {
|
||||
// _route.component = route.component || resolveComponent(route.code) || BlankLayoutPage
|
||||
// }
|
||||
// }
|
||||
// menusData.push(_route)
|
||||
// silderMenus.push(silder)
|
||||
// })
|
||||
// return {
|
||||
// menusData,
|
||||
// silderMenus,
|
||||
// }
|
||||
// }
|
||||
|
||||
const resolveComponent = (name: any) => {
|
||||
const importPage = pagesComponent[`../views/${name}/index.vue`];
|
||||
if (!importPage) {
|
||||
return undefined
|
||||
} else {
|
||||
const res = () => importPage()
|
||||
return res
|
||||
import { shallowRef } from 'vue'
|
||||
|
||||
type Buttons = Array<{ id: string }>
|
||||
|
||||
const hasAppID = (item: { appId?: string, url?: string }): { isApp: boolean, appUrl: string } => {
|
||||
return {
|
||||
isApp: !!item.appId,
|
||||
appUrl: `/${item.appId}${item.url}`
|
||||
}
|
||||
//@ts-ignore
|
||||
}
|
||||
|
||||
const findChildrenRoute = (code: string, url: string, routes: any[] = []): MenuItem[] => {
|
||||
if (extraRouteObj[code]) {
|
||||
const extraRoutes = extraRouteObj[code].children.map((route: MenuItem) => {
|
||||
return {
|
||||
url: `${url}/${route.code}`,
|
||||
code: `${code}/${route.code}`,
|
||||
name: route.name,
|
||||
isShow: false
|
||||
}
|
||||
})
|
||||
return [...routes, ...extraRoutes]
|
||||
}
|
||||
return routes
|
||||
const handleButtons = (buttons?: Buttons) => {
|
||||
return buttons?.map((b) => b.id) || []
|
||||
}
|
||||
|
||||
const findDetailRouteItem = (code: string, url: string): Partial<MenuItem> | null => {
|
||||
const detailComponent = resolveComponent(`${code}/Detail`)
|
||||
const handleMeta = (item: MenuItem, isApp: boolean) => {
|
||||
return {
|
||||
icon: item.icon,
|
||||
title: item.name,
|
||||
hideInMenu: item.isShow === false,
|
||||
buttons: handleButtons(item.buttons),
|
||||
isApp
|
||||
}
|
||||
}
|
||||
|
||||
const findComponents = (code: string, level: number, isApp: boolean, components: any) => {
|
||||
const myComponents = components[code]
|
||||
if (level === 1) { // BasicLayoutPage
|
||||
return myComponents ? () => myComponents() : BasicLayoutPage
|
||||
} else if (level === 2) { // BlankLayoutPage or components
|
||||
return myComponents ? () => myComponents() : BlankLayoutPage
|
||||
} else if (isApp){ // iframe
|
||||
return () => Iframe
|
||||
} else if(myComponents) { // components
|
||||
return () => myComponents()
|
||||
}
|
||||
// return components['demo'] // 开发测试用
|
||||
return undefined
|
||||
}
|
||||
|
||||
const hasExtraChildren = (item: MenuItem, extraMenus: any ) => {
|
||||
const extraItem = extraMenus[item.code]
|
||||
if (extraItem) {
|
||||
return extraItem.children.map(e => ({
|
||||
...e,
|
||||
url: `${item.url}${e.url}`,
|
||||
isShow: false
|
||||
}))
|
||||
}
|
||||
|
||||
return undefined
|
||||
}
|
||||
|
||||
export const getAsyncRoutesMap = () => {
|
||||
const modules = {}
|
||||
Object.keys(pagesComponent).forEach(item => {
|
||||
const code = item.replace('../views/', '').replace('/index.vue', '')
|
||||
modules[code] = pagesComponent[item]
|
||||
})
|
||||
return modules
|
||||
}
|
||||
|
||||
const findDetailRouteItem = (item: any, components: any) => {
|
||||
const { code, url } = item
|
||||
const detailComponent = components[`${item.code}/Detail`]
|
||||
if (detailComponent) {
|
||||
return {
|
||||
return [{
|
||||
url: `${url}/detail/:id`,
|
||||
code: `${code}/Detail`,
|
||||
component: detailComponent,
|
||||
name: '详情信息',
|
||||
isShow: false
|
||||
}
|
||||
}]
|
||||
}
|
||||
return null
|
||||
return []
|
||||
}
|
||||
|
||||
const findDetailRoutes = (routes: any[]): any[] => {
|
||||
const newRoutes: any[] = []
|
||||
routes.forEach((route: any) => {
|
||||
newRoutes.push(route)
|
||||
const detail = findDetailRouteItem(route.code, route.url)
|
||||
if (detail) {
|
||||
newRoutes.push(detail)
|
||||
}
|
||||
})
|
||||
return newRoutes
|
||||
}
|
||||
|
||||
const filterMenus = ['device/DashBoard']
|
||||
export const filterCommunityMenus = (menuData: any[]) => {
|
||||
return menuData.filter(item => {
|
||||
if (item.children) {
|
||||
item.children = filterCommunityMenus(item.children)
|
||||
}
|
||||
return !filterMenus.includes(item.code)
|
||||
})
|
||||
}
|
||||
|
||||
export const findCodeRoute = (asyncRouterMap: any[]) => {
|
||||
const routeMeta = {}
|
||||
|
||||
function getDetail(code: string, url: string) {
|
||||
const detail = findDetailRouteItem(code, url)
|
||||
if (!detail) return
|
||||
|
||||
routeMeta[(detail as MenuItem).code] = {
|
||||
path: detail.url,
|
||||
title: detail.name,
|
||||
parentName: code,
|
||||
buttons: detail.buttons?.map((b: any) => b.id) || []
|
||||
}
|
||||
}
|
||||
|
||||
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) || []
|
||||
export const handleMenus = (menuData: any[], components: any, level: number = 1) => {
|
||||
if (menuData && menuData.length) {
|
||||
return menuData.map(item => {
|
||||
const { isApp, appUrl } = hasAppID(item) // 是否为第三方程序
|
||||
const meta = handleMeta(item, isApp)
|
||||
const route: any = {
|
||||
path: isApp ? appUrl : `${item.url}`,
|
||||
name: isApp ? appUrl : item.code,
|
||||
url: isApp ? appUrl : item.url,
|
||||
meta: meta,
|
||||
children: item.children
|
||||
}
|
||||
const otherRoutes = extraRouteObj[route.code]
|
||||
|
||||
if (otherRoutes) {
|
||||
otherRoutes.children.map((item: any) => {
|
||||
const _code = `${route.code}/${item.code}`
|
||||
const url = `${route.url}/${item.code}`
|
||||
routeMeta[_code] = {
|
||||
path: `${route.url}/${item.code}`,
|
||||
title: item.name,
|
||||
parentName: route.code,
|
||||
buttons: item.buttons?.map((b: any) => b.id) || []
|
||||
}
|
||||
getDetail(_code, url)
|
||||
})
|
||||
route.component = findComponents(item.code, level, isApp, components)
|
||||
const extraRoute = hasExtraChildren(item, extraRouteObj)
|
||||
const detail_components = findDetailRouteItem(item, components)
|
||||
|
||||
|
||||
if (extraRoute && !isApp) { // 包含额外的子路由
|
||||
route.children = route.children ? [...route.children, ...extraRoute] : extraRoute
|
||||
}
|
||||
const _code = route.appId ? `/${route.appId}${route.url}` : route.code
|
||||
if (!route.appId) {
|
||||
getDetail(_code, route.url)
|
||||
} else {
|
||||
routeMeta[_code] = {
|
||||
path: `/${route.appId}${route.url}`,
|
||||
title: route.name,
|
||||
parentName: code,
|
||||
buttons: []
|
||||
}
|
||||
|
||||
if (detail_components.length) {
|
||||
route.children = route.children ? route.children.concat(detail_components) : detail_components
|
||||
}
|
||||
if (route.children) {
|
||||
findChildren(route.children, _code)
|
||||
|
||||
if (route.children && route.children.length) {
|
||||
route.children = handleMenus(route.children, components, level + 1)
|
||||
}
|
||||
|
||||
const showChildren = route.children?.filter(r => !r.meta?.hideInMenu) || []
|
||||
|
||||
if (route.children && route.children.length && showChildren.length) {
|
||||
route.redirect = showChildren[0].path
|
||||
}
|
||||
|
||||
return route
|
||||
})
|
||||
}
|
||||
|
||||
findChildren(asyncRouterMap)
|
||||
|
||||
return routeMeta
|
||||
return []
|
||||
}
|
||||
|
||||
export function filterAsyncRouter(asyncRouterMap: any, parentCode = '', level = 1): { menusData: any, silderMenus: any } {
|
||||
const _asyncRouterMap = cloneDeep(asyncRouterMap)
|
||||
const menusData: any[] = []
|
||||
const silderMenus: any[] = []
|
||||
_asyncRouterMap.forEach((route: any) => {
|
||||
const hasAppId = route.appId
|
||||
const _route: any = {
|
||||
path: hasAppId ? `/${route.appId}${route.url}` : `${route.url}`,
|
||||
name: hasAppId ? `/${route.appId}${route.url}` : route.code,
|
||||
url: hasAppId ? `/${route.appId}${route.url}` : route.url,
|
||||
meta: {
|
||||
icon: route.icon,
|
||||
title: route.name,
|
||||
hideInMenu: route.isShow === false,
|
||||
buttons: route.buttons?.map((b: any) => b.id) || [],
|
||||
isApp: hasAppId,
|
||||
},
|
||||
}
|
||||
|
||||
const silder = { ..._route }
|
||||
// 查看是否有隐藏子路由
|
||||
route.children = findChildrenRoute(route.code, route.url, route.children)
|
||||
route.children = findDetailRoutes(route.children)
|
||||
if (route.children && route.children.length) {
|
||||
// TODO 查看是否具有详情页
|
||||
const { menusData: _menusData, silderMenus: _silderMenus } = filterAsyncRouter(route.children, `${parentCode}/${route.code}`, level + 1)
|
||||
_route.children = _menusData
|
||||
silder.children = _silderMenus
|
||||
const showChildren = _route.children.some((r: any) => !r.meta.hideInMenu)
|
||||
|
||||
if (showChildren && _route.children.length) {
|
||||
_route.component = level === 1 ? BasicLayoutPage : BlankLayoutPage
|
||||
_route.redirect = _route.children[0].url
|
||||
} else {
|
||||
const myComponent = resolveComponent(route.code)
|
||||
// _route.component = myComponent ? myComponent : BlankLayoutPage;
|
||||
if (!!myComponent) {
|
||||
_route.component = myComponent;
|
||||
_route.children.map((r: any) => menusData.push(r))
|
||||
delete _route.children
|
||||
} else {
|
||||
_route.component = BlankLayoutPage
|
||||
}
|
||||
export const handleMenusMap = (menuData: any[], cb: (data: any) => void) => {
|
||||
if (menuData && menuData.length) {
|
||||
menuData.forEach(item => {
|
||||
cb(item)
|
||||
if (item.children) {
|
||||
handleMenusMap(item.children, cb)
|
||||
}
|
||||
} else {
|
||||
if (hasAppId) {
|
||||
_route.component = route.component || resolveComponent('iframe')
|
||||
} else {
|
||||
_route.component = route.component || resolveComponent(route.code) || BlankLayoutPage
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const hideInMenu = (code: string) => {
|
||||
return ['account-center', 'message-subscribe'].includes(code)
|
||||
}
|
||||
|
||||
export const handleSiderMenu = (menuData: any[]) => {
|
||||
if (menuData && menuData.length) {
|
||||
return menuData.map(item => {
|
||||
const { isApp, appUrl } = hasAppID(item) // 是否为第三方程序
|
||||
const meta = handleMeta(item, isApp)
|
||||
const route: any = {
|
||||
path: isApp ? appUrl : `${item.url}`,
|
||||
name: isApp ? appUrl : item.code,
|
||||
url: isApp ? appUrl : item.url,
|
||||
meta: meta,
|
||||
children: item.children
|
||||
}
|
||||
}
|
||||
menusData.push(_route)
|
||||
silderMenus.push(silder)
|
||||
})
|
||||
return {
|
||||
menusData,
|
||||
silderMenus,
|
||||
|
||||
if (route.children && route.children.length) {
|
||||
route.children = handleSiderMenu(route.children)
|
||||
}
|
||||
|
||||
route.meta.hideInMenu = hideInMenu(item.code)
|
||||
|
||||
return route
|
||||
})
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
||||
|
||||
export const handleAuthMenu = (menuData: any[], cb: (code: any, buttons: any[]) => void) => {
|
||||
if (menuData && menuData.length) {
|
||||
return menuData.forEach(item => {
|
||||
const { code, buttons, children} = item
|
||||
|
||||
if (buttons) {
|
||||
cb(code, buttons.map(a => a.id))
|
||||
}
|
||||
|
||||
if (children) {
|
||||
handleAuthMenu(children, cb)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -277,7 +277,7 @@ const initPage = async (newId: any) => {
|
|||
}
|
||||
|
||||
onBeforeRouteUpdate((to: any) => {
|
||||
if (to.params?.id!==instanceStore.current.id) {
|
||||
if (to.params?.id!==instanceStore.current.id && to.name === 'device/Instance/Detail') {
|
||||
initPage(to.params?.id)
|
||||
}
|
||||
})
|
||||
|
|
|
@ -192,7 +192,7 @@ import type {
|
|||
ProductItem,
|
||||
} from '@/views/device/Product/typings';
|
||||
import type { PropType } from 'vue';
|
||||
import { onBeforeRouteLeave } from 'vue-router'
|
||||
import {useRouter, onBeforeRouteUpdate} from 'vue-router'
|
||||
import { useMetadata, useOperateLimits } from './hooks';
|
||||
import {TypeStringMap, useColumns} from './columns';
|
||||
import { levelMap, sourceMap, expandsType, limitsMap } from './utils';
|
||||
|
@ -211,6 +211,8 @@ import { Modal } from 'jetlinks-ui-components'
|
|||
import {EventEmitter} from "@/utils/utils";
|
||||
import {watch} from "vue";
|
||||
import {cloneDeep} from "lodash";
|
||||
import {useSystem} from "store/system";
|
||||
import {storeToRefs} from "pinia";
|
||||
|
||||
const props = defineProps({
|
||||
target: {
|
||||
|
@ -229,6 +231,10 @@ const props = defineProps({
|
|||
|
||||
const _target = inject<'device' | 'product'>('_metadataType', props.target);
|
||||
|
||||
const system = useSystem();
|
||||
const {basicLayout} = storeToRefs(system);
|
||||
const router = useRouter()
|
||||
|
||||
const { data: metadata, noEdit, productNoEdit } = useMetadata(_target, props.type);
|
||||
const { hasOperate } = useOperateLimits(_target);
|
||||
|
||||
|
@ -337,28 +343,11 @@ const handleAddClick = async (_data?: any, index?: number) => {
|
|||
|
||||
const newObject = _data || getDataByType()
|
||||
|
||||
|
||||
|
||||
// const data = [...dataSource.value];
|
||||
//
|
||||
// if (index !== undefined) {
|
||||
// // 校验
|
||||
// const _data = await tableRef.value.getData()
|
||||
// console.log(_data)
|
||||
// if (_data) {
|
||||
// data.splice(index + 1, 0, newObject);
|
||||
// }
|
||||
// } else {
|
||||
// data.push(newObject);
|
||||
// }
|
||||
// dataSource.value = data
|
||||
const _addData = await tableRef.value.addItem(newObject, index)
|
||||
if (_addData.length === 1) {
|
||||
showLastDelete.value = true
|
||||
}
|
||||
showSave.value = true
|
||||
// const _index = index !== undefined ? index + 1 : 0
|
||||
// tableRef.value?.addItemAll?.(_index)
|
||||
};
|
||||
|
||||
const copyItem = (record: any, index: number) => {
|
||||
|
@ -452,16 +441,24 @@ const tabsChange = inject('tabsChange')
|
|||
|
||||
const parentTabsChange = (next?: Function) => {
|
||||
if (editStatus.value) {
|
||||
Modal.confirm({
|
||||
const modal = Modal.confirm({
|
||||
content: '页面改动数据未保存',
|
||||
okText: '保存',
|
||||
cancelText: '不保存',
|
||||
zIndex: 1400,
|
||||
closable: true,
|
||||
onOk: () => {
|
||||
handleSaveClick(next as Function)
|
||||
},
|
||||
onCancel: () => {
|
||||
(next as Function)?.()
|
||||
onCancel: (e: any) => {
|
||||
if (!e.triggerCancel) { // 取消按钮
|
||||
modal.destroy();
|
||||
(next as Function)?.()
|
||||
} else {// 右上角取消按钮
|
||||
const paths = router.currentRoute.value.matched
|
||||
basicLayout.value.selectedKeys = paths.map(item => item.path)
|
||||
basicLayout.value.openKeys = paths.map(item => item.path)
|
||||
}
|
||||
}
|
||||
})
|
||||
} else {
|
||||
|
@ -479,7 +476,7 @@ watch(() => metadata.value, () => {
|
|||
dataSource.value = metadata.value
|
||||
}, { immediate: true })
|
||||
|
||||
onBeforeRouteLeave((to, from, next) => {
|
||||
onBeforeRouteUpdate((to, from, next) => {
|
||||
parentTabsChange(next as Function)
|
||||
})
|
||||
|
||||
|
|
Loading…
Reference in New Issue