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

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

@ -1,65 +1,65 @@ @@ -1,65 +1,65 @@
// 路由收集器 - 收集前端路由信息
import router from '@/router'
import { RouteUtils } from './RouteUtils.js'
// 加载生成的路由映射文件
const generatedMapping = RouteUtils.loadGeneratedMapping()
import { mainRoutes } from './generated-route-mapping.js'
// 路由收集器
export class RouteCollector {
constructor() {
this.routes = []
}
// 收集所有路由信息
// 收集路由
collectRoutes() {
this.routes = []
// 如果存在生成的路由映射,使用它
if (generatedMapping && generatedMapping.mainRoutes) {
console.log('🔧 使用生成的路由映射文件')
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}`)
try {
// 从生成的路由映射文件收集
if (!mainRoutes || !Array.isArray(mainRoutes)) {
console.warn('⚠ 生成的路由映射文件格式不正确')
return []
}
})
return this.routes
}
// 从生成的路由映射收集
_collectFromGeneratedMapping() {
if (!generatedMapping || !generatedMapping.mainRoutes) {
console.warn('⚠ 生成的路由映射文件无效,无法收集路由')
return
}
// 转换为主入口路由格式
const frontendRoutes = mainRoutes.map(route => {
// 确保模块信息正确
if (!route.module) {
route.module = this._extractModuleFromPath(route.path)
}
console.log('📋 从生成的路由映射收集主入口路由:')
generatedMapping.mainRoutes.forEach(route => {
this.routes.push({
path: route.path,
name: route.name,
module: route.module,
description: route.description,
type: route.type
return {
path: route.path,
name: route.name,
module: route.module,
description: route.description || route.name,
type: route.type || 'list'
}
})
console.log(`✅ 添加主入口路由: ${route.path} -> 模块: ${route.module}`)
})
this.routes = frontendRoutes
return frontendRoutes
} catch (error) {
console.error('❌ 从生成的路由映射文件收集路由失败:', error)
return []
}
}
// 从路径中提取模块名
// 从路径提取模块名
_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 @@ @@ -1,34 +1,58 @@
// 路由映射器 - 将前端路由映射到后端API
import { RouteUtils } from './RouteUtils.js'
import { subRouteMappings, moduleApiMappings } from './generated-route-mapping.js'
export class RouteMapper {
constructor() {
// 加载生成的路由映射文件
const generatedMapping = RouteUtils.loadGeneratedMapping()
// 保存子路由映射
this.subRouteMappings = generatedMapping?.subRouteMappings || {}
this.defaultApiMappings = {
'user-management': {
basePath: '/auth/admin/users',
operations: {
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) {
const mappings = []
console.log('🔗 开始生成路由映射,前端路由数量:', frontendRoutes.length)
frontendRoutes.forEach((route, index) => {
console.log(`🔗 处理路由 ${index + 1}:`, {
path: route.path,
name: route.name,
module: route.module,
description: route.description
})
const apiMappings = this._generateApiMappingsForRoute(route)
console.log(`🔗 路由 ${index + 1} 生成的映射数量:`, apiMappings.length)
mappings.push(...apiMappings)
const routeMappings = this._generateApiMappingsForRoute(route)
mappings.push(...routeMappings)
})
console.log('🔗 总共生成映射数量:', mappings.length)
return mappings
}
@ -37,106 +61,104 @@ export class RouteMapper { @@ -37,106 +61,104 @@ export class RouteMapper {
const mappings = []
const module = route.module
console.log(`🔗 为路由生成API映射: 模块=${module}, 路径=${route.path}`)
// 检查模块信息是否完整
if (!module) {
console.error(`❌ 路由缺少模块信息: ${route.path}`)
// 尝试从路径中提取模块
const extractedModule = this._extractModuleFromPath(route.path)
console.log(`🔍 尝试从路径提取模块: ${route.path} -> ${extractedModule}`)
route.module = extractedModule
return mappings
}
// 检查是否是子路由,如果是则映射到主路由
const subRouteMapping = this.subRouteMappings[route.path]
// 检查是否有子路由映射
const subRouteMapping = this._getSubRouteMapping(route.path)
if (subRouteMapping) {
console.log(`🔗 检测到子路由映射: ${route.path} -> ${subRouteMapping.mainRoute} (操作: ${subRouteMapping.operation})`)
// 子路由的API映射会通过主路由处理,这里不需要单独处理
return mappings
const mapping = this._createApiMapping(route, subRouteMapping.operation)
if (mapping) {
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
}
// 创建默认映射
_createDefaultMapping(route) {
const mapping = {
frontend_route: route.path,
backend_route: `/api/${route.module}`,
http_method: 'GET',
module: route.module,
description: `${route.description} - 默认API`,
auth_group: 'Read',
status: 1
// 创建API映射
_createApiMapping(route, operation) {
const module = route.module
const apiConfig = this._getApiConfigForModule(module)
if (!apiConfig || !apiConfig.operations || !apiConfig.operations[operation]) {
return null
}
console.log(`🔗 创建默认映射:`, mapping)
return mapping
}
// 生成API描述
_generateApiDescription(route, operation) {
const method = operation.method
const routeDesc = route.description
const operationConfig = apiConfig.operations[operation]
switch (method) {
case 'GET':
return `获取${routeDesc}`
case 'POST':
return `创建${routeDesc}`
case 'PUT':
return `更新${routeDesc}`
case 'DELETE':
return `删除${routeDesc}`
default:
return `${method}操作 - ${routeDesc}`
if (!operationConfig || operationConfig.path === undefined || !operationConfig.method) {
return null
}
return {
frontend_route: route.path,
backend_route: `${apiConfig.basePath}${operationConfig.path}`,
http_method: operationConfig.method,
module: module,
operation: operation
}
}
// 获取权限分组
_getAuthGroup(method) {
const editMethods = ['POST', 'PUT', 'PATCH', 'DELETE']
return editMethods.includes(method) ? 'Edit' : 'Read'
// 获取子路由映射
_getSubRouteMapping(routePath) {
try {
return subRouteMappings[routePath] || null
} catch (error) {
return null
}
}
// 从路径中提取模块名(备用方法)
_extractModuleFromPath(path) {
return RouteUtils.extractModuleFromPath(path)
// 获取模块的API配置
_getApiConfigForModule(module) {
// 首先尝试从生成的路由映射文件获取
try {
if (moduleApiMappings && moduleApiMappings[module]) {
return moduleApiMappings[module]
}
} catch (error) {
// 如果获取失败,使用默认配置
}
// 使用默认配置
return this.defaultApiMappings[module]
}
// 验证映射的完整性
// 验证映射完整性
validateMappings(mappings) {
const errors = []
console.log('🔍 开始验证映射完整性...')
mappings.forEach((mapping, index) => {
console.log(`🔍 验证映射 ${index}:`, {
frontend_route: mapping.frontend_route,
backend_route: mapping.backend_route,
http_method: mapping.http_method,
module: mapping.module,
description: mapping.description
})
const validation = RouteUtils.validateMapping(mapping, index)
if (!validation.isValid) {
errors.push(...validation.errors)
if (!mapping.frontend_route) {
errors.push(`映射 ${index}: 缺少前端路由`)
}
if (!mapping.backend_route) {
errors.push(`映射 ${index}: 缺少后端路由`)
}
if (!mapping.http_method) {
errors.push(`映射 ${index}: 缺少HTTP方法`)
}
if (!mapping.module) {
errors.push(`映射 ${index}: 缺少模块信息`)
}
})
console.log('🔍 验证完成,错误数量:', errors.length)
return {
isValid: errors.length === 0,
errors
errors: errors
}
}
}

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

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

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

@ -1,149 +1,63 @@ @@ -1,149 +1,63 @@
// 路由同步服务 - 负责与后端API通信并同步路由信息
import { RouteCollector } from './RouteCollector'
import { RouteMapper } from './RouteMapper'
import axios from 'axios'
// 路由同步服务
export class RouteSyncService {
constructor(apiBaseUrl = 'http://localhost:8080') {
this.apiBaseUrl = apiBaseUrl
this.routeCollector = new RouteCollector()
this.routeMapper = new RouteMapper()
this.syncStatus = {
lastSync: null,
totalRoutes: 0,
syncedRoutes: 0,
errors: []
}
this.axios = axios.create({
baseURL: apiBaseUrl,
timeout: 10000
})
}
// 执行路由同步
async syncRoutes() {
// 同步路由到后端
async syncRoutes(routeMappings) {
try {
console.log('🔄 开始同步前端路由到后端...')
// 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
if (!routeMappings || routeMappings.length === 0) {
return { success: false, errors: ['没有路由映射需要同步'] }
}
// 按模块分组路由映射
const moduleGroups = this._groupMappingsByModule(routeMappings)
// 4. 同步到后端
const syncResult = await this._syncToBackend(routeMappings)
// 5. 更新同步状态
this.syncStatus = {
lastSync: new Date(),
totalRoutes: frontendRoutes.length,
syncedRoutes: routeMappings.length,
errors: syncResult.errors || []
const results = {
success: true,
errors: [],
details: {}
}
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) {
const results = {
success: 0,
errors: []
}
// 按模块分组处理,避免重复同步
const moduleGroups = this._groupMappingsByModule(routeMappings)
for (const [module, mappings] of Object.entries(moduleGroups)) {
try {
console.log(`🔄 同步模块 "${module}" 的 ${mappings.length} 个映射...`)
// 构建前台路由数据
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
})
// 逐个模块同步
for (const [module, mappings] of Object.entries(moduleGroups)) {
try {
const result = await this._syncModule(module, mappings)
results.details[module] = result
if (!result.success) {
results.success = false
results.errors.push(...result.errors)
}
} catch (error) {
results.success = false
results.errors.push(`模块 "${module}" 同步失败: ${error.message}`)
results.details[module] = { success: false, error: error.message }
}
} catch (error) {
console.error(`❌ 模块 "${module}" 同步失败:`, error)
results.errors.push({
module,
error: error.message
})
}
return results
} catch (error) {
return {
success: false,
errors: [`同步失败: ${error.message}`]
}
}
return results
}
// 按模块分组映射
_groupMappingsByModule(routeMappings) {
_groupMappingsByModule(mappings) {
const groups = {}
routeMappings.forEach(mapping => {
mappings.forEach(mapping => {
const module = mapping.module
if (!groups[module]) {
groups[module] = []
@ -154,28 +68,63 @@ export class RouteSyncService { @@ -154,28 +68,63 @@ export class RouteSyncService {
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) {
// 按前台路由分组
const frontendRouteGroups = {}
mappings.forEach(mapping => {
const frontendRoute = mapping.frontend_route
if (!frontendRouteGroups[frontendRoute]) {
frontendRouteGroups[frontendRoute] = {
path: frontendRoute,
name: frontendRoute.split('/').pop() || 'default',
component: 'Unknown',
name: this._extractRouteName(frontendRoute),
component: this._generateComponent(frontendRoute, module),
module: module,
description: mapping.description,
sort: 0,
description: this._generateDescription(frontendRoute, module),
sort: this._generateSort(frontendRoute, module),
type: this._determineRouteType(frontendRoute, module),
backend_routes: []
}
}
// 检查是否已存在相同的后台路由
// 检查是否已存在相同的后路由
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) {
@ -183,138 +132,93 @@ export class RouteSyncService { @@ -183,138 +132,93 @@ export class RouteSyncService {
backend_route: mapping.backend_route,
http_method: mapping.http_method,
module: module,
description: mapping.description
description: mapping.operation || 'unknown'
})
} else {
console.log(` 跳过重复的后台路由: ${mapping.backend_route} (${mapping.http_method})`)
}
})
// 转换为数组格式(批量同步期望数组)
return Object.values(frontendRouteGroups)
}
// 同步单个映射(保留原有方法,用于兼容)
async _syncSingleMapping(mapping) {
try {
console.log(`🔄 同步映射: ${mapping.frontend_route} -> ${mapping.backend_route}`)
// 构建前台路由数据
const frontendRouteData = {
path: mapping.frontend_route,
name: mapping.frontend_route.split('/').pop() || 'default',
component: 'Unknown',
module: mapping.module,
description: mapping.description,
sort: 0,
backend_routes: [{
backend_route: mapping.backend_route,
http_method: mapping.http_method,
module: mapping.module,
description: mapping.description
}]
}
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
// 提取路由名称
_extractRouteName(path) {
if (path === '/' || path === '') return 'Home'
const segments = path.split('/').filter(Boolean)
if (segments.length === 0) return 'Home'
const lastSegment = segments[segments.length - 1]
return lastSegment.charAt(0).toUpperCase() + lastSegment.slice(1)
}
// 生成描述
_generateDescription(path, module) {
const descriptions = {
'home': '首页',
'user-management': '用户管理',
'role-management': '角色管理',
'system-settings': '系统设置',
'route-sync': '路由同步测试'
}
return descriptions[module] || `${this._extractRouteName(path)}页面`
}
// 获取同步状态
getSyncStatus() {
return {
...this.syncStatus,
isSynced: this.syncStatus.lastSync !== null && this.syncStatus.errors.length === 0
// 确定路由类型
_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'
}
// 获取前端路由信息
getFrontendRoutes() {
return this.routeCollector.collectRoutes()
}
// 获取路由映射
getRouteMappings() {
const frontendRoutes = this.routeCollector.collectRoutes()
return this.routeMapper.generateRouteMappings(frontendRoutes)
}
// 按模块获取路由
getRoutesByModule() {
return this.routeCollector.getRoutesByModule()
}
// 获取菜单路由
getMenuRoutes() {
return this.routeCollector.getMenuRoutes()
}
// 获取操作路由
getOperationRoutes() {
return this.routeCollector.getOperationRoutes()
}
// 添加自定义API映射
addApiMapping(module, config) {
this.routeMapper.addApiMapping(module, config)
// 生成组件名称
_generateComponent(path, module) {
if (path === '/' || path === '') return 'Home'
const segments = path.split('/').filter(Boolean)
if (segments.length === 0) return 'Home'
const lastSegment = segments[segments.length - 1]
const componentName = lastSegment.charAt(0).toUpperCase() + lastSegment.slice(1)
// 特殊处理某些路径
if (path === '/route-sync') {
return 'RouteSync'
}
return componentName
}
// 设置API基础URL
setApiBaseUrl(url) {
this.apiBaseUrl = url
// 生成排序值
_generateSort(path, module) {
const sortMap = {
'home': 1,
'user-management': 10,
'role-management': 20,
'system-settings': 30,
'route-sync': 100
}
return sortMap[module] || 50
}
// 手动触发同步
async manualSync() {
console.log('🔄 手动触发路由同步...')
return await this.syncRoutes()
async manualSync(routeMappings) {
return await this.syncRoutes(routeMappings)
}
// 获取同步统计信息
getSyncStats() {
const frontendRoutes = this.routeCollector.collectRoutes()
const routeMappings = this.routeMapper.generateRouteMappings(frontendRoutes)
const routesByModule = this.routeCollector.getRoutesByModule()
const operationRoutes = this.routeCollector.getOperationRoutes()
// 获取同步状态
getSyncStatus() {
return {
frontendRoutes: frontendRoutes.length,
routeMappings: routeMappings.length,
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
apiBaseUrl: this.apiBaseUrl,
isConnected: true
}
}
}

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

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

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

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

Loading…
Cancel
Save