From 70d32e311babb2af861548b15d769064ea58801a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E6=88=90?= Date: Wed, 8 Oct 2025 19:59:17 +0800 Subject: [PATCH] 1 --- demo-project/src/main.js | 12 +++++- src/index.js | 42 ++++++++++++++++++++ src/utils/uiTool.js | 82 +++++++++++++++++++++++++++++++++++----- 3 files changed, 126 insertions(+), 10 deletions(-) diff --git a/demo-project/src/main.js b/demo-project/src/main.js index 88293ec..62ed583 100644 --- a/demo-project/src/main.js +++ b/demo-project/src/main.js @@ -26,7 +26,17 @@ Vue.use(AdminFramework, { createPersistedState }) -// 添加自定义业务路由(可选) +// 添加自定义组件映射(用于权限菜单中的组件路径) +// 当后端返回的菜单包含这些路径时,会自动加载对应组件 +AdminFramework.addComponentMap({ + 'business/product_list.vue': ProductList, + 'business/product_list': ProductList + // 如果有更多业务组件,在这里添加: + // 'ball/games.vue': GamesComponent, + // 'order/pay_orders.vue': PayOrdersComponent, +}) + +// 添加自定义业务路由(手动添加的路由) const businessRoutes = [ { path: '/business/product', diff --git a/src/index.js b/src/index.js index 0d4c4e3..24f2915 100644 --- a/src/index.js +++ b/src/index.js @@ -146,6 +146,9 @@ class AdminFramework { // 自动注册全局组件 this.registerGlobalComponents(Vue) + + // 自动设置组件映射表 + this.setupComponentMap() // 如果提供了 Vuex,自动创建 Store if (Vuex && !this.store) { @@ -186,6 +189,45 @@ class AdminFramework { // 注册登录页面 Vue.component('LoginPage', LoginPage) } + + /** + * 设置组件映射表(将后端返回的路径映射到实际组件) + */ + setupComponentMap() { + // 组件列表:路径 => 组件 + const components = { + 'home/index': HomePage, + 'system/sys_log': SysLog, + 'system/sys_param_setup': SysParamSetup, + 'system/sys_role': SysRole, + 'system/sys_user': SysUser, + 'system_high/sys_control': SysControl, + 'system_high/sys_menu': SysMenu, + 'system_high/sys_title': SysTitle + } + + // 自动生成带 .vue 和不带 .vue 的映射 + const map = {} + Object.keys(components).forEach(path => { + map[path] = components[path] + map[path + '.vue'] = components[path] + }) + + uiTool.setComponentMap(map) + } + + /** + * 添加自定义组件映射 + * @param {Object} customMap - 自定义组件映射对象 + * @example + * AdminFramework.addComponentMap({ + * 'ball/games.vue': GamesComponent, + * 'order/pay_orders.vue': PayOrdersComponent + * }) + */ + addComponentMap(customMap) { + uiTool.setComponentMap(customMap) + } /** * 初始化 HTTP 配置 diff --git a/src/utils/uiTool.js b/src/utils/uiTool.js index 9db98e8..c7b63d0 100644 --- a/src/utils/uiTool.js +++ b/src/utils/uiTool.js @@ -1,6 +1,32 @@ import http from './http' +// 组件映射表(将后端返回的路径映射到实际组件) +const componentMap = {} + export default class uiTool { + + /** + * 设置组件映射表 + * @param {Object} map - 组件映射对象 + */ + static setComponentMap(map) { + Object.assign(componentMap, map) + } + + /** + * 根据路径获取组件 + * @param {String} componentPath - 组件路径(如 "system/sys_user.vue") + * @returns {Component} 组件或 null + */ + static getComponent(componentPath) { + if (!componentPath) return null + + // 标准化路径(移除 .vue 后缀) + const normalizedPath = componentPath.replace(/\.vue$/, '') + + // 从映射表中查找 + return componentMap[normalizedPath] || componentMap[componentPath] + } static setRem() { let whdef = 100 / 1920 let bodyWidth = document.body.clientWidth @@ -142,11 +168,29 @@ export default class uiTool { item.component = ParentView } else if (item.type === '页面' || item.type === '功能') { try { - let componentName = item.component - // 这里需要在使用时动态导入 - item.componentPath = componentName - item.component = Page404 + let componentPath = item.component + + // 从组件映射表中获取组件 + let component = uiTool.getComponent(componentPath) + + if (component) { + // 找到了对应的组件 + item.component = component + } else { + // 未找到组件,使用占位组件并记录路径 + console.warn(`组件未找到: ${componentPath},使用占位组件`) + item.component = { + render: h => h('div', { style: { padding: '20px' } }, [ + h('Alert', { props: { type: 'warning' } }, [ + h('p', `页面组件未加载: ${componentPath}`), + h('p', '请在项目中创建此组件或在组件映射表中注册') + ]) + ]) + } + item.componentPath = componentPath + } } catch (e) { + console.error('组件加载失败:', e) item.component = Page404 } } else { @@ -156,7 +200,8 @@ export default class uiTool { item.meta = { icon: item.icon, isMenu: item.is_show_menu, - type: item.type + type: item.type, + title: item.name } if (item.children && item.children.length > 0) { @@ -168,14 +213,24 @@ export default class uiTool { return [] } - static getRoutes(Main, ParentView, Page404) { + static getRoutes(Main, ParentView, Page404, HomePage) { let mainRoute = { path: '/', name: '主视图', redirect: '/home', component: Main, meta: { title: '首页', notCache: true }, - children: [] + children: [ + // 默认 home 路由,确保登录后能跳转 + { + path: '/home', + name: 'home', + meta: { title: '首页', notCache: true }, + component: HomePage || { + render: h => h('div', { style: { padding: '20px' } }, '欢迎使用管理系统') + } + } + ] } // 从 localStorage 读取权限菜单 @@ -189,8 +244,17 @@ export default class uiTool { let menus = uiTool.transformTree(authorityMenus) let curRoutes = uiTool.menuToRoute(menus, ParentView, Page404) - // 使用后端返回的路由(包括首页) - mainRoute.children = curRoutes + // 合并权限路由,保留默认 home 路由 + const homeRoute = mainRoute.children.find(r => r.name === 'home') + const hasHome = curRoutes.some(r => r.name === 'home') + + if (hasHome) { + // 如果权限路由中有 home,使用权限路由的 home + mainRoute.children = curRoutes + } else { + // 如果权限路由中没有 home,保留默认 home 并添加其他路由 + mainRoute.children = [homeRoute, ...curRoutes] + } } }