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