7.0 KiB
7.0 KiB
路由生成逻辑重构说明
重构目标
将 Platform 中的通用路由生成逻辑提取到 shared 包中,使其他 web 服务也可以复用。
架构设计
职责划分
Shared 包(shared/utils/route)
- ✅ 提供通用的路由生成方法
- ✅ 提供视图树构建方法
- ✅ 提供 localStorage 数据加载方法
- ✅ 不依赖特定的 router 实例
- ✅ 不依赖特定的组件加载方式
Platform 包(platform/src/router/dynamicRoute.ts)
- ✅ 提供 Platform 特定的布局组件映射
- ✅ 提供 Platform 特定的组件加载器
- ✅ 调用 shared 中的通用方法
- ✅ 将生成的路由添加到 Platform 的 router 实例
核心方法
Shared 包新增方法
1. generateSimpleRoutes()
export function generateSimpleRoutes(
views: TbSysViewDTO[],
config: RouteGeneratorConfig,
options?: GenerateSimpleRoutesOptions
): RouteRecordRaw[]
功能:生成简化的路由配置,适合直接添加到 router
参数:
views- 视图列表config- 路由生成器配置(布局映射、组件加载器等)options- 可选配置asRootChildren- 是否作为根路由的子路由iframePlaceholder- iframe 类型视图的占位组件verbose- 是否启用详细日志
返回:路由配置数组
2. loadViewsFromStorage()
export function loadViewsFromStorage(
storageKey?: string,
viewsPath?: string
): TbSysViewDTO[] | null
功能:从 localStorage 加载视图数据
参数:
storageKey- localStorage 的 key(默认:'loginDomain')viewsPath- 视图数据在对象中的路径(默认:'userViews',支持嵌套如 'user.views')
返回:视图列表,如果不存在返回 null
Platform 包简化后的方法
1. addDynamicRoutes()
export function addDynamicRoutes(views: TbSysViewDTO[]) {
// 使用 shared 中的通用方法生成路由
const routes = generateSimpleRoutes(views, routeConfig, routeOptions)
// 将生成的路由添加到 Platform 的 router
routes.forEach(route => {
router.addRoute('Root', route)
})
}
2. loadRoutesFromStorage()
export function loadRoutesFromStorage(): boolean {
// 使用 shared 中的通用方法加载视图数据
const views = loadViewsFromStorage('loginDomain', 'userViews')
if (views) {
addDynamicRoutes(views)
return true
}
return false
}
使用示例
在 Platform 中使用
import { loadRoutesFromStorage, addDynamicRoutes } from '@/router/dynamicRoute'
// 从 localStorage 加载并添加路由
loadRoutesFromStorage()
// 或者手动传入视图数据
const views = [...] // 从 API 获取
addDynamicRoutes(views)
在其他 Web 服务中使用
import {
generateSimpleRoutes,
loadViewsFromStorage,
type RouteGeneratorConfig
} from 'shared/utils/route'
import router from './router'
// 1. 配置路由生成器
const config: RouteGeneratorConfig = {
layoutMap: {
'MyLayout': () => import('./layouts/MyLayout.vue')
},
viewLoader: (path) => {
// 自定义组件加载逻辑
return () => import(`./views/${path}.vue`)
}
}
// 2. 加载视图数据
const views = loadViewsFromStorage()
// 3. 生成路由
if (views) {
const routes = generateSimpleRoutes(views, config, {
asRootChildren: true,
verbose: true
})
// 4. 添加到 router
routes.forEach(route => {
router.addRoute('Root', route)
})
}
配置说明
RouteGeneratorConfig
interface RouteGeneratorConfig {
/** 布局组件映射表 */
layoutMap: Record<string, () => Promise<any>>
/** 视图组件加载器 */
viewLoader: (componentPath: string) => (() => Promise<any>) | null
/** 静态路由列表(可选) */
staticRoutes?: RouteRecordRaw[]
/** 404 组件(可选) */
notFoundComponent?: () => Promise<any>
}
GenerateSimpleRoutesOptions
interface GenerateSimpleRoutesOptions {
/** 是否作为根路由的子路由(路径去掉前导 /) */
asRootChildren?: boolean
/** iframe 类型视图的占位组件 */
iframePlaceholder?: () => Promise<any>
/** 是否启用详细日志 */
verbose?: boolean
}
优势
1. 代码复用
- ✅ 通用逻辑只需维护一份
- ✅ 其他 web 服务可以直接使用
- ✅ 减少重复代码
2. 职责清晰
- ✅ Shared 负责通用逻辑
- ✅ 各个服务负责特定配置
- ✅ 易于理解和维护
3. 灵活性
- ✅ 通过配置注入实现定制化
- ✅ 支持多种使用方式
- ✅ 易于扩展
4. 可测试性
- ✅ 通用方法独立测试
- ✅ 配置化便于 mock
- ✅ 减少耦合
迁移指南
如果其他服务想要使用 shared 中的路由生成逻辑:
步骤 1:准备配置
// 1. 准备布局组件映射
const layoutMap = {
'MainLayout': () => import('./layouts/MainLayout.vue'),
'BlankLayout': () => import('./layouts/BlankLayout.vue')
}
// 2. 准备组件加载器
const VIEW_MODULES = import.meta.glob('./views/**/*.vue')
const viewLoader = (path: string) => {
const fullPath = `./views/${path}.vue`
return VIEW_MODULES[fullPath] || null
}
// 3. 组装配置
const config: RouteGeneratorConfig = {
layoutMap,
viewLoader
}
步骤 2:加载视图数据
import { loadViewsFromStorage } from 'shared/utils/route'
// 从 localStorage 加载
const views = loadViewsFromStorage('loginDomain', 'userViews')
// 或从 API 加载
// const views = await api.getUserViews()
步骤 3:生成并添加路由
import { generateSimpleRoutes } from 'shared/utils/route'
if (views) {
const routes = generateSimpleRoutes(views, config, {
asRootChildren: true,
verbose: process.env.NODE_ENV === 'development'
})
routes.forEach(route => {
router.addRoute('YourRootRouteName', route)
})
}
注意事项
- 组件加载器:每个服务的组件路径可能不同,需要自行实现
viewLoader - 布局组件:需要提供服务特定的布局组件映射
- 路由实例:需要自行将生成的路由添加到服务的 router 实例
- iframe 支持:如果需要支持 iframe 视图,需要提供占位组件
文件变更
新增文件
shared/src/utils/route/route-generator.ts- 新增通用方法
修改文件
shared/src/utils/route/index.ts- 新增导出shared/vite.config.ts- 新增导出配置shared/EXPOSES.md- 更新文档platform/src/router/dynamicRoute.ts- 简化代码platform/src/types/shared.d.ts- 新增类型声明
更新日志
2025-12-12
- ✅ 将路由生成通用逻辑提取到 shared
- ✅ 新增
generateSimpleRoutes方法 - ✅ 新增
loadViewsFromStorage方法 - ✅ 简化 Platform 的 dynamicRoute.ts
- ✅ 更新文档和类型声明