# 路由生成逻辑重构说明

## 重构目标

将 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
- ✅ 更新文档和类型声明
