ソースを参照

feat: 菜单管理 parentRoute & parentName 对接 拼装

lanceJiang 1 年間 前
コミット
bc808866e9

+ 5 - 4
src/api/system/menu.ts

@@ -1,6 +1,6 @@
 import request from '@/utils/request'
 import { AxiosPromise } from 'axios'
-import { local_permissionsMenuList } from '@/router'
+import { localDemoRoutes, local_permissionsMenuList } from '@/router'
 
 /**
  * 获取路由列表
@@ -22,9 +22,10 @@ export function getMenuList(): AxiosPromise {
 		url: '/sys/resource/list-menu-permissions',
 		method: 'get',
 		extraConfig: { showFullscreenLoading: true }
-	}) /*.then(res => {
+	}).then(res => {
 		console.error(JSON.stringify(res), 'res...')
-		// res['menu'] = [res.menu[0]/!*, res.menu[1]*!/]
+		// res['menu'] = [res.menu[0]/*, res.menu[1]*/]
+		res['menu'].unshift(...localDemoRoutes)
 		return res
 		// return Promise.resolve({
 		// 	// 路由菜单
@@ -32,5 +33,5 @@ export function getMenuList(): AxiosPromise {
 		// 	// 权限
 		// 	permissions: ['']
 		// })
-	})*/
+	})
 }

+ 127 - 122
src/router/index.ts

@@ -5,8 +5,7 @@ import useStore from '@/store'
 export const Layout = () => import('@/layout/index.vue')
 
 const HOME_URL = '/dashboard'
-// 是否展示示例相关菜单
-const showDemoRoutes = !!import.meta.env.DEV
+
 // 参数说明: https://panjiachen.github.io/vue-element-admin-site/guide/essentials/router-and-nav.html
 // 静态路由
 export const sysStaticRouter: Array<AppRouteRecordRaw> = [
@@ -57,6 +56,131 @@ export const sysErrorRoutes = [
 		meta: { hidden: true }
 	}
 ]
+// 展示示例相关菜单
+export const localDemoRoutes = !!import.meta.env.DEV
+	? [
+			// 外部链接
+			{
+				path: '/external-link',
+				component: Layout,
+				children: [
+					{
+						path: 'https://github.com/LanceJiang/Lance-Element-Admin',
+						meta: { title: '外部链接', icon: 'icon-link' }
+					}
+				]
+			},
+			// 组件示例
+			{
+				path: '/components',
+				component: Layout,
+				redirect: '/index',
+				children: [
+					{
+						path: 'index',
+						component: () => import('@/views/components/index.vue'),
+						name: 'comps',
+						meta: { title: 'comps', icon: 'icon-excel' }
+					}
+				]
+			},
+			// 表单示例
+			{
+				/*path: '/form',
+		component: Layout,
+		// meta: { title: 'Form', icon: 'guide' },
+		redirect: '/default',
+		children: [
+			{
+				path: 'default',
+				component: () => import('@/views/form/default.vue'),
+				name: 'FormDefault',
+				meta: { title: 'form', icon: 'icon-guide' }
+			}
+		]*/
+				path: 'default',
+				component: () => import('@/views/form/default.vue'),
+				name: 'FormDefault',
+				meta: { title: 'form', icon: 'icon-guide', parentName: 'mainLayout' }
+			},
+			// 列表示例
+			{
+				path: '/table',
+				component: Layout,
+				redirect: 'default',
+				meta: { title: 'table', icon: 'icon-table' },
+				children: [
+					{
+						path: 'default',
+						component: () => import('@/views/table/default.vue'),
+						name: 'TableDefault',
+						meta: { title: 'table' /*, icon: 'table'*/ }
+					},
+					{
+						path: 'multipleHeader',
+						component: () => import('@/views/table/multipleHeader.vue'),
+						name: 'multipleHeader',
+						meta: { title: 'multipleHeader' }
+					},
+					{
+						path: 'treeTable',
+						component: () => import('@/views/table/treeTable.vue'),
+						name: 'treeTable',
+						meta: { title: 'treeTable' }
+					},
+					{
+						path: 'mergeCells',
+						component: () => import('@/views/table/mergeCells.vue'),
+						name: 'mergeCells',
+						meta: { title: 'mergeCells' }
+					},
+					{
+						path: 'footerSummary',
+						component: () => import('@/views/table/footerSummary.vue'),
+						name: 'footerSummary',
+						meta: { title: 'footerSummary' }
+					},
+					{
+						path: 'expandTable',
+						component: () => import('@/views/table/expandTable.vue'),
+						name: 'expandTable',
+						meta: { title: 'expandTable' }
+					},
+					{
+						path: 'resizeParentHeightTable',
+						component: () => import('@/views/table/resizeParentHeightTable.vue'),
+						name: 'resizeParentHeightTable',
+						meta: { title: 'resizeParentHeightTable' }
+					}
+				]
+			},
+			{
+				// demo演示
+				path: '/demo',
+				component: 'Layout',
+				redirect: '/demo/adminManage',
+				meta: { title: 'demo', icon: 'icon-peoples' },
+				children: [
+					{
+						// path: '/demo/pageConfig',
+						path: 'pageConfig',
+						// component: () => import('@/views/demo/pageConfig/index'),
+						component: 'demo/pageConfig/index',
+						name: 'pageConfig',
+						meta: { title: 'demo_pageConfig', icon: 'le-fangda1' }
+					},
+					{
+						// 管理员管理
+						// path: '/demo/adminManage',
+						path: 'adminManage',
+						name: 'adminManage',
+						component: 'demo/adminManage/index',
+						meta: { title: 'demo_adminManage', icon: 'Setting' }
+					}
+				]
+			}
+	  ]
+	: []
 
 export const constantRoutes: AppRouteRecordRaw[] = [
 	// 首页
@@ -67,126 +191,7 @@ export const constantRoutes: AppRouteRecordRaw[] = [
 		name: 'dashboard',
 		meta: { title: 'dashboard', icon: 'icon-homepage', affix: true, parentName: 'mainLayout' }
 	},
-	/*// 外部链接
-	{
-		path: '/external-link',
-		component: Layout,
-		children: [
-			{
-				path: 'https://github.com/LanceJiang/Lance-Element-Admin',
-				meta: { title: '外部链接', icon: 'icon-link' }
-			}
-		]
-	},*/
-	...(showDemoRoutes
-		? [
-				// 组件示例
-				{
-					path: '/components',
-					component: Layout,
-					redirect: '/index',
-					children: [
-						{
-							path: 'index',
-							component: () => import('@/views/components/index.vue'),
-							name: 'comps',
-							meta: { title: 'comps', icon: 'icon-excel' }
-						}
-					]
-				},
-				// 表单示例
-				{
-					path: '/form',
-					component: Layout,
-					// meta: { title: 'Form', icon: 'guide' },
-					redirect: '/default',
-					children: [
-						{
-							path: 'default',
-							component: () => import('@/views/form/default.vue'),
-							name: 'FormDefault',
-							meta: { title: 'form', icon: 'icon-guide' }
-						}
-					]
-				},
-				// 列表示例
-				{
-					path: '/table',
-					component: Layout,
-					redirect: 'default',
-					meta: { title: 'table', icon: 'icon-table' },
-					children: [
-						{
-							path: 'default',
-							component: () => import('@/views/table/default.vue'),
-							name: 'TableDefault',
-							meta: { title: 'table' /*, icon: 'table'*/ }
-						},
-						{
-							path: 'multipleHeader',
-							component: () => import('@/views/table/multipleHeader.vue'),
-							name: 'multipleHeader',
-							meta: { title: 'multipleHeader' }
-						},
-						{
-							path: 'treeTable',
-							component: () => import('@/views/table/treeTable.vue'),
-							name: 'treeTable',
-							meta: { title: 'treeTable' }
-						},
-						{
-							path: 'mergeCells',
-							component: () => import('@/views/table/mergeCells.vue'),
-							name: 'mergeCells',
-							meta: { title: 'mergeCells' }
-						},
-						{
-							path: 'footerSummary',
-							component: () => import('@/views/table/footerSummary.vue'),
-							name: 'footerSummary',
-							meta: { title: 'footerSummary' }
-						},
-						{
-							path: 'expandTable',
-							component: () => import('@/views/table/expandTable.vue'),
-							name: 'expandTable',
-							meta: { title: 'expandTable' }
-						},
-						{
-							path: 'resizeParentHeightTable',
-							component: () => import('@/views/table/resizeParentHeightTable.vue'),
-							name: 'resizeParentHeightTable',
-							meta: { title: 'resizeParentHeightTable' }
-						}
-					]
-				},
-				{
-					// demo演示
-					path: '/demo',
-					component: 'Layout',
-					redirect: '/demo/adminManage',
-					meta: { title: 'demo', icon: 'icon-peoples' },
-					children: [
-						{
-							// path: '/demo/pageConfig',
-							path: 'pageConfig',
-							// component: () => import('@/views/demo/pageConfig/index'),
-							component: 'demo/pageConfig/index',
-							name: 'pageConfig',
-							meta: { title: 'demo_pageConfig', icon: 'le-fangda1' }
-						},
-						{
-							// 管理员管理
-							// path: '/demo/adminManage',
-							path: 'adminManage',
-							name: 'adminManage',
-							component: 'demo/adminManage/index',
-							meta: { title: 'demo_adminManage', icon: 'Setting' }
-						}
-					]
-				}
-		  ]
-		: []),
+	...localDemoRoutes,
 	// 用户
 	{
 		path: '/profile',

+ 2 - 0
src/router/types.ts

@@ -22,12 +22,14 @@ export interface MetaProps {
 	// 不缓存路由
 	noCache?: boolean
 	// 当前路由配置添加到 哪个父级: router.addRoute([parentName], route)
+	// !!! 由于原有tree-list 有当前字段,固目前用接口拿 parentRoute 过来进行替换
 	parentName?: string
 
 	// todo???
 	activeMenu?: string
 	// // todo???
 	// roles?: string[]
+	[key: string]: any
 }
 // eslint-disable-next-line
 // @ts-ignore

+ 4 - 0
src/store/modules/permission.ts

@@ -31,6 +31,10 @@ export const filterAsyncRoutes = (routes: AppRouteRecordRaw[], roles: string[],
 		tmp.meta = tmp.meta ? tmp.meta : {}
 		// 默认icon
 		tmp.meta.icon = tmp.meta.icon || 'menu'
+		// 从接口上对 parentRoute 进行置换 为 parentName
+		if (tmp.meta?.parentRoute) {
+			tmp.meta.parentName = tmp.meta.parentRoute
+		}
 		// path全链 重组
 		// tmp.path = /\/.*/.test(tmp.path) ? tmp.path : `${parentPath}/${tmp.path}`
 		tmp.path = /\/.+/.test(tmp.path) ? tmp.path : `${parentPath}/${tmp.path}`

+ 12 - 1
src/views/setting/menu/save.vue

@@ -34,6 +34,13 @@
 							<el-radio-button label="3">按钮</el-radio-button>
 						</el-radio-group>
 					</el-form-item>
+					<el-form-item label="父级别名" prop="parentRoute">
+						<el-input v-model="form.parentRoute" placeholder="指定父级别名: 主入口(mainLayout)"></el-input>
+						<div class="el-form-item-msg">
+							若有指定父级菜单,才需要填写。 <br />
+							若插入主入口: “<span style="color: var(--el-color-warning)">mainLayout</span>”
+						</div>
+					</el-form-item>
 					<el-form-item label="别名" prop="alias">
 						<el-input v-model="form.alias" clearable placeholder="菜单别名"></el-input>
 						<div class="el-form-item-msg">系统唯一且与内置组件名一致,否则导致缓存失效。如类型为Iframe的菜单,别名将代替源地址显示在地址栏</div>
@@ -131,7 +138,9 @@ const form = ref({
 	color: '',
 	type: '0',
 	sort: 0,
-	apiList: []
+	apiList: [],
+	// 指定父级菜单(路由)名称
+	parentRoute: ''
 })
 const i18n_formTitle = computed(() => {
 	return generateTitle(form.value.title)
@@ -210,10 +219,12 @@ h2 {
 }
 
 .el-form-item-msg {
+	margin-top: 6px;
 	font-size: 12px;
 	color: #999;
 	clear: both;
 	width: 100%;
+	line-height: 16px;
 }
 :deep(.local_form-item_title) {
 	.el-form-item__label {