Browse Source

路由同步第一阶段完成

master
hejl 4 days ago
parent
commit
3d6208a152
  1. 2071
      gofaster/app/dist/renderer/js/index.js
  2. 12
      gofaster/app/src/renderer/main.js
  3. 94
      gofaster/app/src/renderer/modules/route-sync/RouteCollector.js
  4. 200
      gofaster/app/src/renderer/modules/route-sync/RouteMapper.js
  5. 295
      gofaster/app/src/renderer/modules/route-sync/RouteSyncManager.js
  6. 394
      gofaster/app/src/renderer/modules/route-sync/RouteSyncService.js
  7. 110
      gofaster/app/src/renderer/modules/route-sync/RouteUtils.js
  8. 2
      gofaster/app/src/renderer/modules/route-sync/generated-route-mapping.js
  9. 2
      gofaster/app/src/renderer/modules/route-sync/index.js
  10. 6
      gofaster/app/src/renderer/router/index.js

2071
gofaster/app/dist/renderer/js/index.js vendored

File diff suppressed because it is too large Load Diff

12
gofaster/app/src/renderer/main.js

@ -139,7 +139,7 @@ import '@fortawesome/fontawesome-free/css/all.min.css'
import { initDB } from './modules/core/services/db' import { initDB } from './modules/core/services/db'
// 初始化路由同步管理器 // 初始化路由同步管理器
import routeSyncManager from './modules/route-sync' import RouteSyncManager from './modules/route-sync'
// 应用启动函数 // 应用启动函数
async function startApp() { async function startApp() {
@ -164,16 +164,15 @@ async function startApp() {
// 4. 初始化路由同步管理器 // 4. 初始化路由同步管理器
console.log('🔄 初始化路由同步管理器...') console.log('🔄 初始化路由同步管理器...')
console.log('routeSyncManager:', routeSyncManager)
console.log('routeSyncManager类型:', typeof routeSyncManager) // 创建路由同步管理器实例
console.log('routeSyncManager.initialize:', typeof routeSyncManager.initialize) const routeSyncManager = new RouteSyncManager()
console.log('✅ 路由同步管理器实例创建成功:', routeSyncManager)
// 检查RouteSyncService是否可用 // 检查RouteSyncService是否可用
try { try {
const { RouteSyncService } = await import('./modules/route-sync/RouteSyncService.js') const { RouteSyncService } = await import('./modules/route-sync/RouteSyncService.js')
console.log('✅ RouteSyncService 导入成功:', RouteSyncService) console.log('✅ RouteSyncService 导入成功:', RouteSyncService)
console.log('RouteSyncService类型:', typeof RouteSyncService)
console.log('RouteSyncService构造函数:', typeof RouteSyncService === 'function' ? '可用' : '不可用')
} catch (error) { } catch (error) {
console.error('❌ RouteSyncService 导入失败:', error) console.error('❌ RouteSyncService 导入失败:', error)
} }
@ -185,6 +184,7 @@ async function startApp() {
syncInterval: 5 * 60 * 1000, // 5分钟 syncInterval: 5 * 60 * 1000, // 5分钟
retryAttempts: 3 retryAttempts: 3
}) })
console.log('✅ 路由同步管理器初始化完成')
} else { } else {
console.error('❌ routeSyncManager 或 initialize 方法不可用') console.error('❌ routeSyncManager 或 initialize 方法不可用')
} }

94
gofaster/app/src/renderer/modules/route-sync/RouteCollector.js

@ -1,65 +1,65 @@
// 路由收集器 - 收集前端路由信息 // 路由收集器 - 收集前端路由信息
import router from '@/router' import { mainRoutes } from './generated-route-mapping.js'
import { RouteUtils } from './RouteUtils.js'
// 加载生成的路由映射文件
const generatedMapping = RouteUtils.loadGeneratedMapping()
// 路由收集器
export class RouteCollector { export class RouteCollector {
constructor() { constructor() {
this.routes = [] this.routes = []
} }
// 收集所有路由信息 // 收集路由
collectRoutes() { collectRoutes() {
this.routes = [] try {
// 从生成的路由映射文件收集
// 如果存在生成的路由映射,使用它 if (!mainRoutes || !Array.isArray(mainRoutes)) {
if (generatedMapping && generatedMapping.mainRoutes) { console.warn('⚠ 生成的路由映射文件格式不正确')
console.log('🔧 使用生成的路由映射文件') return []
this._collectFromGeneratedMapping()
} else {
console.log('🔧 生成的路由映射文件不存在,无法收集路由')
console.warn('⚠ 请确保 route-mapping-plugin 已正确生成路由映射文件')
}
// 检查所有路由的模块信息
console.log('🔍 检查收集到的路由模块信息:')
this.routes.forEach((route, index) => {
if (!route.module) {
console.error(`❌ 路由 ${index} 缺少模块信息:`, route)
// 尝试重新提取模块信息
route.module = this._extractModuleFromPath(route.path)
console.log(`🔧 重新提取模块信息: ${route.path} -> ${route.module}`)
} }
})
return this.routes
}
// 从生成的路由映射收集 // 转换为主入口路由格式
_collectFromGeneratedMapping() { const frontendRoutes = mainRoutes.map(route => {
if (!generatedMapping || !generatedMapping.mainRoutes) { // 确保模块信息正确
console.warn('⚠ 生成的路由映射文件无效,无法收集路由') if (!route.module) {
return route.module = this._extractModuleFromPath(route.path)
} }
console.log('📋 从生成的路由映射收集主入口路由:') return {
generatedMapping.mainRoutes.forEach(route => { path: route.path,
this.routes.push({ name: route.name,
path: route.path, module: route.module,
name: route.name, description: route.description || route.name,
module: route.module, type: route.type || 'list'
description: route.description, }
type: route.type
}) })
console.log(`✅ 添加主入口路由: ${route.path} -> 模块: ${route.module}`)
}) this.routes = frontendRoutes
return frontendRoutes
} catch (error) {
console.error('❌ 从生成的路由映射文件收集路由失败:', error)
return []
}
} }
// 从路径中提取模块名 // 从路径提取模块名
_extractModuleFromPath(path) { _extractModuleFromPath(path) {
return RouteUtils.extractModuleFromPath(path) if (path === '/' || path === '') return 'home'
const segments = path.split('/').filter(Boolean)
if (segments.length === 0) return 'home'
// 获取第一个段作为模块名
const module = segments[0]
// 映射模块名
const moduleMap = {
'user-management': 'user-management',
'role-management': 'role-management',
'settings': 'system-settings',
'user-profile': 'user-management',
'route-sync': 'route-sync'
}
return moduleMap[module] || module
} }
// 获取菜单路由 // 获取菜单路由

200
gofaster/app/src/renderer/modules/route-sync/RouteMapper.js

@ -1,34 +1,58 @@
// 路由映射器 - 将前端路由映射到后端API // 路由映射器 - 将前端路由映射到后端API
import { RouteUtils } from './RouteUtils.js' import { RouteUtils } from './RouteUtils.js'
import { subRouteMappings, moduleApiMappings } from './generated-route-mapping.js'
export class RouteMapper { export class RouteMapper {
constructor() { constructor() {
// 加载生成的路由映射文件 this.defaultApiMappings = {
const generatedMapping = RouteUtils.loadGeneratedMapping() 'user-management': {
basePath: '/auth/admin/users',
// 保存子路由映射 operations: {
this.subRouteMappings = generatedMapping?.subRouteMappings || {} list: { path: '', method: 'GET' },
create: { path: '', method: 'POST' },
update: { path: '/:id', method: 'PUT' },
delete: { path: '/:id', method: 'DELETE' },
detail: { path: '/:id', method: 'GET' },
getRoles: { path: '/roles', method: 'GET' }
}
},
'role-management': {
basePath: '/auth/roles',
operations: {
list: { path: '', method: 'GET' },
create: { path: '', method: 'POST' },
update: { path: '/:id', method: 'PUT' },
delete: { path: '/:id', method: 'DELETE' },
detail: { path: '/:id', method: 'GET' }
}
},
'system-settings': {
basePath: '/auth/settings',
operations: {
list: { path: '', method: 'GET' },
update: { path: '', method: 'PUT' }
}
},
'route-sync': {
basePath: '/auth/route-sync',
operations: {
list: { path: '', method: 'GET' },
test: { path: '/test', method: 'POST' },
status: { path: '/status', method: 'GET' }
}
}
}
} }
// 生成前端路由到后端API的映射 // 生成路由映射
generateRouteMappings(frontendRoutes) { generateRouteMappings(frontendRoutes) {
const mappings = [] const mappings = []
console.log('🔗 开始生成路由映射,前端路由数量:', frontendRoutes.length)
frontendRoutes.forEach((route, index) => { frontendRoutes.forEach((route, index) => {
console.log(`🔗 处理路由 ${index + 1}:`, { const routeMappings = this._generateApiMappingsForRoute(route)
path: route.path, mappings.push(...routeMappings)
name: route.name,
module: route.module,
description: route.description
})
const apiMappings = this._generateApiMappingsForRoute(route)
console.log(`🔗 路由 ${index + 1} 生成的映射数量:`, apiMappings.length)
mappings.push(...apiMappings)
}) })
console.log('🔗 总共生成映射数量:', mappings.length)
return mappings return mappings
} }
@ -37,106 +61,104 @@ export class RouteMapper {
const mappings = [] const mappings = []
const module = route.module const module = route.module
console.log(`🔗 为路由生成API映射: 模块=${module}, 路径=${route.path}`)
// 检查模块信息是否完整
if (!module) { if (!module) {
console.error(`❌ 路由缺少模块信息: ${route.path}`) console.error(`❌ 路由缺少模块信息: ${route.path}`)
// 尝试从路径中提取模块 return mappings
const extractedModule = this._extractModuleFromPath(route.path)
console.log(`🔍 尝试从路径提取模块: ${route.path} -> ${extractedModule}`)
route.module = extractedModule
} }
// 检查是否是子路由,如果是则映射到主路由 // 检查是否有子路由映射
const subRouteMapping = this.subRouteMappings[route.path] const subRouteMapping = this._getSubRouteMapping(route.path)
if (subRouteMapping) { if (subRouteMapping) {
console.log(`🔗 检测到子路由映射: ${route.path} -> ${subRouteMapping.mainRoute} (操作: ${subRouteMapping.operation})`) const mapping = this._createApiMapping(route, subRouteMapping.operation)
// 子路由的API映射会通过主路由处理,这里不需要单独处理 if (mapping) {
return mappings mappings.push(mapping)
}
} else {
// 生成基本API映射
const apiConfig = this._getApiConfigForModule(module)
if (apiConfig && apiConfig.operations) {
Object.keys(apiConfig.operations).forEach(operation => {
const mapping = this._createApiMapping(route, operation)
if (mapping) {
mappings.push(mapping)
}
})
}
} }
// 由于删除了硬编码的API映射,现在只生成基本的默认映射
console.log(`🔍 为模块 "${module}" 生成基本API映射`)
// 生成基本的CRUD API映射
mappings.push(this._createDefaultMapping(route))
console.log(`🔗 生成的映射数量: ${mappings.length}`)
return mappings return mappings
} }
// 创建默认映射 // 创建API映射
_createDefaultMapping(route) { _createApiMapping(route, operation) {
const mapping = { const module = route.module
frontend_route: route.path, const apiConfig = this._getApiConfigForModule(module)
backend_route: `/api/${route.module}`,
http_method: 'GET', if (!apiConfig || !apiConfig.operations || !apiConfig.operations[operation]) {
module: route.module, return null
description: `${route.description} - 默认API`,
auth_group: 'Read',
status: 1
} }
console.log(`🔗 创建默认映射:`, mapping) const operationConfig = apiConfig.operations[operation]
return mapping
}
// 生成API描述
_generateApiDescription(route, operation) {
const method = operation.method
const routeDesc = route.description
switch (method) { if (!operationConfig || operationConfig.path === undefined || !operationConfig.method) {
case 'GET': return null
return `获取${routeDesc}` }
case 'POST':
return `创建${routeDesc}` return {
case 'PUT': frontend_route: route.path,
return `更新${routeDesc}` backend_route: `${apiConfig.basePath}${operationConfig.path}`,
case 'DELETE': http_method: operationConfig.method,
return `删除${routeDesc}` module: module,
default: operation: operation
return `${method}操作 - ${routeDesc}`
} }
} }
// 获取权限分组 // 获取子路由映射
_getAuthGroup(method) { _getSubRouteMapping(routePath) {
const editMethods = ['POST', 'PUT', 'PATCH', 'DELETE'] try {
return editMethods.includes(method) ? 'Edit' : 'Read' return subRouteMappings[routePath] || null
} catch (error) {
return null
}
} }
// 从路径中提取模块名(备用方法) // 获取模块的API配置
_extractModuleFromPath(path) { _getApiConfigForModule(module) {
return RouteUtils.extractModuleFromPath(path) // 首先尝试从生成的路由映射文件获取
try {
if (moduleApiMappings && moduleApiMappings[module]) {
return moduleApiMappings[module]
}
} catch (error) {
// 如果获取失败,使用默认配置
}
// 使用默认配置
return this.defaultApiMappings[module]
} }
// 验证映射的完整性 // 验证映射完整性
validateMappings(mappings) { validateMappings(mappings) {
const errors = [] const errors = []
console.log('🔍 开始验证映射完整性...')
mappings.forEach((mapping, index) => { mappings.forEach((mapping, index) => {
console.log(`🔍 验证映射 ${index}:`, { if (!mapping.frontend_route) {
frontend_route: mapping.frontend_route, errors.push(`映射 ${index}: 缺少前端路由`)
backend_route: mapping.backend_route, }
http_method: mapping.http_method, if (!mapping.backend_route) {
module: mapping.module, errors.push(`映射 ${index}: 缺少后端路由`)
description: mapping.description }
}) if (!mapping.http_method) {
errors.push(`映射 ${index}: 缺少HTTP方法`)
const validation = RouteUtils.validateMapping(mapping, index) }
if (!validation.isValid) { if (!mapping.module) {
errors.push(...validation.errors) errors.push(`映射 ${index}: 缺少模块信息`)
} }
}) })
console.log('🔍 验证完成,错误数量:', errors.length)
return { return {
isValid: errors.length === 0, isValid: errors.length === 0,
errors errors: errors
} }
} }
} }

295
gofaster/app/src/renderer/modules/route-sync/RouteSyncManager.js

@ -1,246 +1,189 @@
// 路由同步管理器 - 负责在应用启动时自动同步路由 // 路由同步管理器 - 负责在应用启动时自动同步路由
import { RouteSyncService } from './RouteSyncService' import { RouteCollector } from './RouteCollector.js'
import { RouteMapper } from './RouteMapper.js'
import { RouteSyncService } from './RouteSyncService.js'
class RouteSyncManager { // 路由同步管理器
constructor() { export class RouteSyncManager {
console.log('🔧 RouteSyncManager 构造函数被调用') constructor(config = {}) {
this.syncService = null
this.isInitialized = false
this.syncInterval = null
this.config = { this.config = {
autoSync: true, autoSync: true,
syncInterval: 5 * 60 * 1000, // 5分钟 syncInterval: 30000, // 30秒
retryAttempts: 3, retryAttempts: 3,
retryDelay: 1000 // 1秒 retryDelay: 1000, // 1秒
...config
} }
console.log('✅ RouteSyncManager 实例创建完成')
this.routeCollector = null
this.routeMapper = null
this.routeSyncService = null
this.syncTimer = null
this.isInitialized = false
} }
// 初始化路由同步管理器 // 初始化路由同步管理器
async initialize(config = {}) { async initialize() {
console.log('🔄 RouteSyncManager.initialize 方法被调用')
console.log('传入的配置:', config)
if (this.isInitialized) { if (this.isInitialized) {
console.log('🔄 路由同步管理器已初始化')
return return
} }
try { // 创建路由收集器
console.log('⚙ 开始初始化路由同步管理器...') this.routeCollector = new RouteCollector()
// 合并配置 // 创建路由映射器
this.config = { ...this.config, ...config } this.routeMapper = new RouteMapper()
console.log('📋 合并后的配置:', this.config)
// 创建路由同步服务
// 创建路由同步服务 this.routeSyncService = new RouteSyncService()
console.log('🔧 创建路由同步服务...')
this.syncService = new RouteSyncService(this.config.apiBaseUrl || 'http://localhost:8080') // 设置自定义API映射
console.log('✅ 路由同步服务创建完成') if (this.config.customApiMappings) {
this.routeMapper.setCustomApiMappings(this.config.customApiMappings)
// 设置自定义API映射
console.log('🔗 设置自定义API映射...')
this._setupCustomApiMappings()
// 执行初始同步
if (this.config.autoSync) {
console.log('🔄 开始执行初始同步...')
await this.performInitialSync()
} else {
console.log('⏸ 自动同步已禁用')
}
// 设置定时同步
if (this.config.syncInterval > 0) {
console.log('⏰ 设置定时同步...')
this._setupPeriodicSync()
} else {
console.log('⏸ 定时同步已禁用')
}
this.isInitialized = true
console.log('✅ 路由同步管理器初始化完成')
} catch (error) {
console.error('❌ 路由同步管理器初始化失败:', error)
console.error('错误堆栈:', error.stack)
throw error
} }
// 执行初始同步
if (this.config.autoSync) {
await this.performInitialSync()
}
// 注释掉定时同步,只执行一次初始同步
// if (this.config.syncInterval > 0) {
// this.setupPeriodicSync()
// }
this.isInitialized = true
} }
// 执行初始同步 // 执行初始同步
async performInitialSync() { async performInitialSync() {
try { try {
console.log('🔄 执行初始路由同步...') // 收集前端路由
const frontendRoutes = this.routeCollector.collectRoutes()
// 先测试路由收集
const frontendRoutes = this.syncService.getFrontendRoutes()
console.log(`📋 收集到 ${frontendRoutes.length} 个前端路由:`, frontendRoutes)
// 测试路由映射 if (frontendRoutes.length === 0) {
const routeMappings = this.syncService.getRouteMappings() console.error('❌ 没有收集到前端路由')
console.log(`🔗 生成 ${routeMappings.length} 个路由映射:`, routeMappings) return
}
// 生成路由映射
const routeMappings = this.routeMapper.generateRouteMappings(frontendRoutes)
// 执行同步 if (routeMappings.length === 0) {
const success = await this.syncService.syncRoutes() console.error('❌ 没有生成路由映射')
return
}
// 同步到后端
const result = await this.routeSyncService.syncRoutes(routeMappings)
if (success) { if (result.success) {
console.log('✅ 初始路由同步成功') // 初始路由同步成功
this._emitSyncEvent('success', this.syncService.getSyncStatus())
} else { } else {
console.warn('⚠ 初始路由同步部分失败') console.error('❌ 初始路由同步失败:', result.errors)
this._emitSyncEvent('partial', this.syncService.getSyncStatus())
} }
} catch (error) { } catch (error) {
console.error('❌ 初始路由同步失败:', error) console.error('❌ 初始路由同步异常:', error)
this._emitSyncEvent('error', { error: error.message })
// 重试机制
if (this.config.retryAttempts > 0) {
await this._retrySync()
}
} }
} }
// 重试同步 // 重试同步
async _retrySync() { async retrySync(attempt = 1) {
for (let attempt = 1; attempt <= this.config.retryAttempts; attempt++) { if (attempt > this.config.retryAttempts) {
try { console.error(`❌ 重试次数已达上限 (${this.config.retryAttempts})`)
console.log(`🔄 重试路由同步 (${attempt}/${this.config.retryAttempts})...`) return false
}
await new Promise(resolve => setTimeout(resolve, this.config.retryDelay * attempt))
try {
const success = await this.syncService.syncRoutes() await new Promise(resolve => setTimeout(resolve, this.config.retryDelay))
if (success) {
console.log('✅ 重试路由同步成功') const frontendRoutes = this.routeCollector.collectRoutes()
this._emitSyncEvent('retry-success', this.syncService.getSyncStatus()) const routeMappings = this.routeMapper.generateRouteMappings(frontendRoutes)
return const result = await this.routeSyncService.syncRoutes(routeMappings)
}
} catch (error) { if (result.success) {
console.error(`❌ 重试路由同步失败 (${attempt}/${this.config.retryAttempts}):`, error) return true
} else {
return await this.retrySync(attempt + 1)
} }
} catch (error) {
console.error(`❌ 重试同步失败 (${attempt}/${this.config.retryAttempts}):`, error)
return await this.retrySync(attempt + 1)
} }
console.error('❌ 所有重试都失败了')
this._emitSyncEvent('retry-failed', { error: '所有重试都失败了' })
} }
// 设置定时同步 // 设置定时同步
_setupPeriodicSync() { setupPeriodicSync() {
if (this.syncInterval) { if (this.syncTimer) {
clearInterval(this.syncInterval) clearInterval(this.syncTimer)
} }
this.syncInterval = setInterval(async () => { this.syncTimer = setInterval(async () => {
try { try {
console.log('🔄 执行定时路由同步...') const frontendRoutes = this.routeCollector.collectRoutes()
await this.syncService.syncRoutes() const routeMappings = this.routeMapper.generateRouteMappings(frontendRoutes)
await this.routeSyncService.syncRoutes(routeMappings)
} catch (error) { } catch (error) {
console.error('❌ 定时路由同步失败:', error) console.error('❌ 定时路由同步失败:', error)
} }
}, this.config.syncInterval) }, this.config.syncInterval)
console.log(`⏰ 定时路由同步已设置,间隔: ${this.config.syncInterval / 1000}`)
}
// 设置自定义API映射
_setupCustomApiMappings() {
// 这里可以添加自定义的API映射规则
// 例如:
// this.syncService.addApiMapping('custom-module', {
// basePath: '/api/custom',
// operations: {
// list: { method: 'GET', path: '' },
// create: { method: 'POST', path: '' }
// }
// })
} }
// 手动触发同步 // 手动触发同步
async manualSync() { async manualSync() {
if (!this.isInitialized) { if (!this.isInitialized) {
throw new Error('路由同步管理器未初始化') console.error('❌ 路由同步管理器未初始化')
return false
} }
return await this.syncService.manualSync()
}
// 获取同步状态
getSyncStatus() {
if (!this.syncService) {
return { isInitialized: false }
}
return this.syncService.getSyncStatus()
}
// 获取同步统计
getSyncStats() {
if (!this.syncService) {
return null
}
return this.syncService.getSyncStats()
}
// 获取前端路由 try {
getFrontendRoutes() { const frontendRoutes = this.routeCollector.collectRoutes()
if (!this.syncService) { const routeMappings = this.routeMapper.generateRouteMappings(frontendRoutes)
return [] const result = await this.routeSyncService.syncRoutes(routeMappings)
return result.success
} catch (error) {
console.error('❌ 手动同步失败:', error)
return false
} }
return this.syncService.getFrontendRoutes()
} }
// 获取路由映射 // 获取同步状态
getRouteMappings() { getSyncStatus() {
if (!this.syncService) { return {
return [] isInitialized: this.isInitialized,
hasSyncTimer: !!this.syncTimer,
syncInterval: this.config.syncInterval,
autoSync: this.config.autoSync
} }
return this.syncService.getRouteMappings()
} }
// 更新配置 // 更新配置
updateConfig(newConfig) { updateConfig(newConfig) {
this.config = { ...this.config, ...newConfig } this.config = {
...this.config,
...newConfig
}
// 如果修改了同步间隔,重新设置定时器 // 如果修改了同步间隔,重新设置定时器
if (newConfig.syncInterval !== undefined) { if (newConfig.syncInterval !== undefined) {
this._setupPeriodicSync() this.setupPeriodicSync()
} }
} }
// 停止同步 // 停止同步
stop() { stop() {
if (this.syncInterval) { if (this.syncTimer) {
clearInterval(this.syncInterval) clearInterval(this.syncTimer)
this.syncInterval = null this.syncTimer = null
} }
this.isInitialized = false
console.log('🛑 路由同步管理器已停止')
} }
// 销毁管理器 // 销毁管理器
destroy() { destroy() {
this.stop() this.stop()
this.syncService = null this.isInitialized = false
console.log('🗑 路由同步管理器已销毁') this.routeCollector = null
} this.routeMapper = null
this.routeSyncService = null
// 发送同步事件
_emitSyncEvent(type, data) {
// 这里可以发送自定义事件,供其他组件监听
const event = new CustomEvent('route-sync', {
detail: { type, data, timestamp: new Date() }
})
window.dispatchEvent(event)
} }
} }
// 创建单例实例
const routeSyncManager = new RouteSyncManager()
export default routeSyncManager

394
gofaster/app/src/renderer/modules/route-sync/RouteSyncService.js

@ -1,149 +1,63 @@
// 路由同步服务 - 负责与后端API通信并同步路由信息 // 路由同步服务 - 负责与后端API通信并同步路由信息
import { RouteCollector } from './RouteCollector' import axios from 'axios'
import { RouteMapper } from './RouteMapper'
// 路由同步服务
export class RouteSyncService { export class RouteSyncService {
constructor(apiBaseUrl = 'http://localhost:8080') { constructor(apiBaseUrl = 'http://localhost:8080') {
this.apiBaseUrl = apiBaseUrl this.apiBaseUrl = apiBaseUrl
this.routeCollector = new RouteCollector() this.axios = axios.create({
this.routeMapper = new RouteMapper() baseURL: apiBaseUrl,
this.syncStatus = { timeout: 10000
lastSync: null, })
totalRoutes: 0,
syncedRoutes: 0,
errors: []
}
} }
// 执行路由同步 // 同步路由到后端
async syncRoutes() { async syncRoutes(routeMappings) {
try { try {
console.log('🔄 开始同步前端路由到后端...') if (!routeMappings || routeMappings.length === 0) {
return { success: false, errors: ['没有路由映射需要同步'] }
// 1. 收集前端路由
const frontendRoutes = this.routeCollector.collectRoutes()
console.log(`📋 收集到 ${frontendRoutes.length} 个前端路由:`, frontendRoutes)
// 检查每个路由的模块信息
frontendRoutes.forEach((route, index) => {
console.log(`🔍 路由 ${index}: path="${route.path}", module="${route.module}", name="${route.name}"`)
})
// 2. 生成路由映射
const routeMappings = this.routeMapper.generateRouteMappings(frontendRoutes)
console.log(`🔗 生成 ${routeMappings.length} 个路由映射:`, routeMappings)
// 3. 验证映射
console.log('🔍 开始验证路由映射...')
const validation = this.routeMapper.validateMappings(routeMappings)
console.log('🔍 验证结果:', validation)
if (!validation.isValid) {
console.error('❌ 路由映射验证失败:', validation.errors)
// 详细显示失败的映射
const failedMappings = routeMappings.filter((_, index) =>
validation.errors.some(error => error.includes(`映射 ${index}:`))
)
console.error('❌ 失败的映射详情:')
failedMappings.forEach((mapping, index) => {
console.error(` 映射 ${index}:`, {
frontend_route: mapping.frontend_route,
backend_route: mapping.backend_route,
http_method: mapping.http_method,
module: mapping.module,
description: mapping.description
})
})
this.syncStatus.errors = validation.errors
return false
} }
// 按模块分组路由映射
const moduleGroups = this._groupMappingsByModule(routeMappings)
// 4. 同步到后端 const results = {
const syncResult = await this._syncToBackend(routeMappings) success: true,
errors: [],
// 5. 更新同步状态 details: {}
this.syncStatus = {
lastSync: new Date(),
totalRoutes: frontendRoutes.length,
syncedRoutes: routeMappings.length,
errors: syncResult.errors || []
} }
console.log(`✅ 路由同步完成: ${syncResult.success} 个成功, ${syncResult.errors?.length || 0} 个错误`)
return syncResult.success > 0
} catch (error) {
console.error('❌ 路由同步失败:', error)
this.syncStatus.errors.push(error.message)
return false
}
}
// 同步到后端 // 逐个模块同步
async _syncToBackend(routeMappings) { for (const [module, mappings] of Object.entries(moduleGroups)) {
const results = { try {
success: 0, const result = await this._syncModule(module, mappings)
errors: [] results.details[module] = result
}
if (!result.success) {
// 按模块分组处理,避免重复同步 results.success = false
const moduleGroups = this._groupMappingsByModule(routeMappings) results.errors.push(...result.errors)
}
for (const [module, mappings] of Object.entries(moduleGroups)) { } catch (error) {
try { results.success = false
console.log(`🔄 同步模块 "${module}" 的 ${mappings.length} 个映射...`) results.errors.push(`模块 "${module}" 同步失败: ${error.message}`)
results.details[module] = { success: false, error: error.message }
// 构建前台路由数据
const frontendRouteData = this._buildFrontendRouteData(module, mappings)
const response = await fetch(`${this.apiBaseUrl}/api/frontend-routes/batch-sync`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
// 这里可以添加认证头
// 'Authorization': `Bearer ${token}`
},
body: JSON.stringify(frontendRouteData)
})
if (!response.ok) {
const errorText = await response.text()
throw new Error(`HTTP ${response.status}: ${response.statusText} - ${errorText}`)
}
const result = await response.json()
console.log(`✅ 模块 "${module}" 同步成功:`, result)
// 检查后端响应格式
if (result.code === 200 && result.message) {
results.success += mappings.length
} else {
console.warn(` 模块 "${module}" 同步响应异常:`, result)
results.errors.push({
module,
error: '同步响应异常',
details: result
})
} }
}
} catch (error) {
console.error(`❌ 模块 "${module}" 同步失败:`, error) return results
results.errors.push({ } catch (error) {
module, return {
error: error.message success: false,
}) errors: [`同步失败: ${error.message}`]
} }
} }
return results
} }
// 按模块分组映射 // 按模块分组映射
_groupMappingsByModule(routeMappings) { _groupMappingsByModule(mappings) {
const groups = {} const groups = {}
routeMappings.forEach(mapping => { mappings.forEach(mapping => {
const module = mapping.module const module = mapping.module
if (!groups[module]) { if (!groups[module]) {
groups[module] = [] groups[module] = []
@ -154,28 +68,63 @@ export class RouteSyncService {
return groups return groups
} }
// 构建前台路由数据 // 同步单个模块
async _syncModule(module, mappings) {
try {
// 构建前端路由数据
const frontendRouteData = this._buildFrontendRouteData(module, mappings)
if (frontendRouteData.length === 0) {
return { success: false, errors: [`模块 "${module}" 没有有效的前端路由数据`] }
}
// 发送到后端
const response = await this.axios.post('/api/frontend-routes/batch-sync', frontendRouteData)
return {
success: true,
data: response.data,
count: frontendRouteData.length
}
} catch (error) {
if (error.response) {
return {
success: false,
errors: [`HTTP ${error.response.status}: ${error.response.data?.message || error.message}`]
}
} else {
return {
success: false,
errors: [`网络错误: ${error.message}`]
}
}
}
}
// 构建前端路由数据
_buildFrontendRouteData(module, mappings) { _buildFrontendRouteData(module, mappings) {
// 按前台路由分组
const frontendRouteGroups = {} const frontendRouteGroups = {}
mappings.forEach(mapping => { mappings.forEach(mapping => {
const frontendRoute = mapping.frontend_route const frontendRoute = mapping.frontend_route
if (!frontendRouteGroups[frontendRoute]) { if (!frontendRouteGroups[frontendRoute]) {
frontendRouteGroups[frontendRoute] = { frontendRouteGroups[frontendRoute] = {
path: frontendRoute, path: frontendRoute,
name: frontendRoute.split('/').pop() || 'default', name: this._extractRouteName(frontendRoute),
component: 'Unknown', component: this._generateComponent(frontendRoute, module),
module: module, module: module,
description: mapping.description, description: this._generateDescription(frontendRoute, module),
sort: 0, sort: this._generateSort(frontendRoute, module),
type: this._determineRouteType(frontendRoute, module),
backend_routes: [] backend_routes: []
} }
} }
// 检查是否已存在相同的后台路由 // 检查是否已存在相同的后路由
const existingRoute = frontendRouteGroups[frontendRoute].backend_routes.find( const existingRoute = frontendRouteGroups[frontendRoute].backend_routes.find(
route => route.backend_route === mapping.backend_route && route.http_method === mapping.http_method route => route.backend_route === mapping.backend_route &&
route.http_method === mapping.http_method
) )
if (!existingRoute) { if (!existingRoute) {
@ -183,138 +132,93 @@ export class RouteSyncService {
backend_route: mapping.backend_route, backend_route: mapping.backend_route,
http_method: mapping.http_method, http_method: mapping.http_method,
module: module, module: module,
description: mapping.description description: mapping.operation || 'unknown'
}) })
} else {
console.log(` 跳过重复的后台路由: ${mapping.backend_route} (${mapping.http_method})`)
} }
}) })
// 转换为数组格式(批量同步期望数组)
return Object.values(frontendRouteGroups) return Object.values(frontendRouteGroups)
} }
// 同步单个映射(保留原有方法,用于兼容) // 提取路由名称
async _syncSingleMapping(mapping) { _extractRouteName(path) {
try { if (path === '/' || path === '') return 'Home'
console.log(`🔄 同步映射: ${mapping.frontend_route} -> ${mapping.backend_route}`)
const segments = path.split('/').filter(Boolean)
// 构建前台路由数据 if (segments.length === 0) return 'Home'
const frontendRouteData = {
path: mapping.frontend_route, const lastSegment = segments[segments.length - 1]
name: mapping.frontend_route.split('/').pop() || 'default', return lastSegment.charAt(0).toUpperCase() + lastSegment.slice(1)
component: 'Unknown', }
module: mapping.module,
description: mapping.description, // 生成描述
sort: 0, _generateDescription(path, module) {
backend_routes: [{ const descriptions = {
backend_route: mapping.backend_route, 'home': '首页',
http_method: mapping.http_method, 'user-management': '用户管理',
module: mapping.module, 'role-management': '角色管理',
description: mapping.description 'system-settings': '系统设置',
}] 'route-sync': '路由同步测试'
}
const response = await fetch(`${this.apiBaseUrl}/api/frontend-routes/sync`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
// 这里可以添加认证头
// 'Authorization': `Bearer ${token}`
},
body: JSON.stringify(frontendRouteData)
})
if (!response.ok) {
const errorText = await response.text()
throw new Error(`HTTP ${response.status}: ${response.statusText} - ${errorText}`)
}
const result = await response.json()
console.log(`✅ 同步成功: ${mapping.frontend_route} -> ${mapping.backend_route}`, result)
// 检查后端响应格式
if (result.code === 200 && result.message) {
return true
} else {
console.warn(` 同步响应异常:`, result)
return false
}
} catch (error) {
console.error(`❌ 同步映射失败: ${mapping.frontend_route} -> ${mapping.backend_route}`, error)
throw error
} }
return descriptions[module] || `${this._extractRouteName(path)}页面`
} }
// 获取同步状态 // 确定路由类型
getSyncStatus() { _determineRouteType(path, module) {
return { if (path === '/' || path === '') return 'home'
...this.syncStatus,
isSynced: this.syncStatus.lastSync !== null && this.syncStatus.errors.length === 0 const typeMap = {
'user-management': 'list',
'role-management': 'list',
'system-settings': 'form',
'route-sync': 'test'
} }
return typeMap[module] || 'list'
} }
// 获取前端路由信息 // 生成组件名称
getFrontendRoutes() { _generateComponent(path, module) {
return this.routeCollector.collectRoutes() if (path === '/' || path === '') return 'Home'
}
const segments = path.split('/').filter(Boolean)
// 获取路由映射 if (segments.length === 0) return 'Home'
getRouteMappings() {
const frontendRoutes = this.routeCollector.collectRoutes() const lastSegment = segments[segments.length - 1]
return this.routeMapper.generateRouteMappings(frontendRoutes) const componentName = lastSegment.charAt(0).toUpperCase() + lastSegment.slice(1)
}
// 特殊处理某些路径
// 按模块获取路由 if (path === '/route-sync') {
getRoutesByModule() { return 'RouteSync'
return this.routeCollector.getRoutesByModule() }
}
return componentName
// 获取菜单路由
getMenuRoutes() {
return this.routeCollector.getMenuRoutes()
}
// 获取操作路由
getOperationRoutes() {
return this.routeCollector.getOperationRoutes()
}
// 添加自定义API映射
addApiMapping(module, config) {
this.routeMapper.addApiMapping(module, config)
} }
// 设置API基础URL // 生成排序值
setApiBaseUrl(url) { _generateSort(path, module) {
this.apiBaseUrl = url const sortMap = {
'home': 1,
'user-management': 10,
'role-management': 20,
'system-settings': 30,
'route-sync': 100
}
return sortMap[module] || 50
} }
// 手动触发同步 // 手动触发同步
async manualSync() { async manualSync(routeMappings) {
console.log('🔄 手动触发路由同步...') return await this.syncRoutes(routeMappings)
return await this.syncRoutes()
} }
// 获取同步统计信息 // 获取同步状态
getSyncStats() { getSyncStatus() {
const frontendRoutes = this.routeCollector.collectRoutes()
const routeMappings = this.routeMapper.generateRouteMappings(frontendRoutes)
const routesByModule = this.routeCollector.getRoutesByModule()
const operationRoutes = this.routeCollector.getOperationRoutes()
return { return {
frontendRoutes: frontendRoutes.length, apiBaseUrl: this.apiBaseUrl,
routeMappings: routeMappings.length, isConnected: true
modules: Object.keys(routesByModule).length,
operationRoutes: operationRoutes.length,
moduleStats: Object.keys(routesByModule).map(module => ({
module,
routes: routesByModule[module].length
})),
lastSync: this.syncStatus.lastSync,
errors: this.syncStatus.errors.length
} }
} }
} }

110
gofaster/app/src/renderer/modules/route-sync/RouteUtils.js

@ -1,80 +1,98 @@
// 路由同步工具类 - 提供公共的工具方法 // 路由工具类
import { mainRoutes, moduleApiMappings, subRouteMappings } from './generated-route-mapping.js'
export class RouteUtils { export class RouteUtils {
// 统一的模块名提取方法 // 从路径提取模块名
static extractModuleFromPath(path) { static extractModuleFromPath(path) {
// 移除开头的斜杠,并处理双斜杠 if (path === '/' || path === '') {
let cleanPath = path.startsWith('/') ? path.substring(1) : path return 'core'
// 处理双斜杠情况
if (cleanPath.startsWith('/')) {
cleanPath = cleanPath.substring(1)
} }
if (!cleanPath) { const segments = path.split('/').filter(Boolean)
console.log(`🔍 路径 "${path}" -> 模块 "core" (空路径)`) if (segments.length === 0) {
return 'core' return 'core'
} }
// 分割路径,直接使用第一部分作为模块名 // 获取第一个段作为模块名
const parts = cleanPath.split('/') const firstPart = segments[0]
const firstPart = parts[0]
// 映射模块名
const moduleMap = {
'user-management': 'user-management',
'role-management': 'role-management',
'settings': 'system-settings',
'user-profile': 'user-management',
'route-sync': 'route-sync'
}
console.log(`🔍 路径 "${path}" -> 模块 "${firstPart}"`) return moduleMap[firstPart] || firstPart
return firstPart
} }
// 统一的文件导入方法 // 加载生成的路由映射文件
static loadGeneratedMapping() { static loadGeneratedMapping() {
try { try {
const mapping = require('./generated-route-mapping.js') // 直接返回导入的数据
console.log('✅ 成功加载生成的路由映射文件') return Promise.resolve({
return mapping mainRoutes,
moduleApiMappings,
subRouteMappings
})
} catch (error) { } catch (error) {
console.warn('⚠ 未找到生成的路由映射文件') console.error('❌ 加载生成的路由映射文件失败:', error)
return null return Promise.resolve(null)
}
}
// 验证路由对象完整性
static validateRoute(route, index = 0) {
const errors = []
if (!route.path) {
errors.push(`路由 ${index}: 缺少路径信息`)
}
if (!route.module) {
errors.push(`路由 ${index}: 缺少模块信息`)
}
if (!route.description) {
errors.push(`路由 ${index}: 缺少描述信息`)
}
return {
isValid: errors.length === 0,
errors
} }
} }
// 验证映射对象完整性 // 验证映射
static validateMapping(mapping, index = 0) { static validateMapping(mapping, index) {
const errors = [] const errors = []
if (!mapping.frontend_route) { if (!mapping.frontend_route) {
errors.push(`映射 ${index}: 缺少前端路由`) errors.push(`映射 ${index}: 缺少前端路由`)
} }
if (!mapping.backend_route) { if (!mapping.backend_route) {
errors.push(`映射 ${index}: 缺少后端路由`) errors.push(`映射 ${index}: 缺少后端路由`)
} }
if (!mapping.http_method) { if (!mapping.http_method) {
errors.push(`映射 ${index}: 缺少HTTP方法`) errors.push(`映射 ${index}: 缺少HTTP方法`)
} }
if (!mapping.module) { if (!mapping.module) {
errors.push(`映射 ${index}: 缺少模块信息`) errors.push(`映射 ${index}: 缺少模块信息`)
} }
return { return {
isValid: errors.length === 0, isValid: errors.length === 0,
errors errors: errors
}
}
// 生成路由描述
static generateDescription(name, module) {
const descriptions = {
'home': '首页',
'user-management': '用户管理',
'role-management': '角色管理',
'system-settings': '系统设置',
'route-sync': '路由同步测试'
}
return descriptions[module] || `${name}页面`
}
// 确定路由类型
static determineRouteType(path, module) {
if (path === '/' || path === '') return 'home'
const typeMap = {
'user-management': 'list',
'role-management': 'list',
'system-settings': 'form',
'route-sync': 'test'
} }
return typeMap[module] || 'list'
} }
} }

2
gofaster/app/src/renderer/modules/route-sync/generated-route-mapping.js

@ -39,7 +39,7 @@ export const mainRoutes = [
"type": "list" "type": "list"
}, },
{ {
"path": "/route-sync-test", "path": "/route-sync",
"name": "RouteSyncTest", "name": "RouteSyncTest",
"module": "route-sync", "module": "route-sync",
"description": "路由同步测试", "description": "路由同步测试",

2
gofaster/app/src/renderer/modules/route-sync/index.js

@ -2,7 +2,7 @@
import { RouteSyncService } from './RouteSyncService' import { RouteSyncService } from './RouteSyncService'
import { RouteCollector } from './RouteCollector' import { RouteCollector } from './RouteCollector'
import { RouteMapper } from './RouteMapper' import { RouteMapper } from './RouteMapper'
import RouteSyncManager from './RouteSyncManager' import { RouteSyncManager } from './RouteSyncManager'
export { RouteSyncService, RouteCollector, RouteMapper, RouteSyncManager } export { RouteSyncService, RouteCollector, RouteMapper, RouteSyncManager }

6
gofaster/app/src/renderer/router/index.js

@ -5,7 +5,6 @@ import Home from '@/modules/core/views/Home.vue'
import { UserManagement, UserProfile } from '@/modules/user-management' import { UserManagement, UserProfile } from '@/modules/user-management'
import { Settings } from '@/modules/system-settings' import { Settings } from '@/modules/system-settings'
import RoleManagement from '@/modules/role-management/views/RoleManagement.vue' import RoleManagement from '@/modules/role-management/views/RoleManagement.vue'
import RouteSyncTest from '@/modules/route-sync/RouteSyncTest.vue'
const routes = [ const routes = [
{ {
@ -36,11 +35,6 @@ const routes = [
path: '/role-management', path: '/role-management',
name: 'RoleManagement', name: 'RoleManagement',
component: RoleManagement component: RoleManagement
},
{
path: '/route-sync-test',
name: 'RouteSyncTest',
component: RouteSyncTest
} }
] ]
} }

Loading…
Cancel
Save