Browse Source

路由收集基本完成

master
hejl 3 days ago
parent
commit
c28faf3bc5
  1. 15
      gofaster/app/dev-enhanced.ps1
  2. 184
      gofaster/app/dist/renderer/js/index.js
  3. 2
      gofaster/app/package.json
  4. 194
      gofaster/app/plugins/route-mapping-plugin.js
  5. 21
      gofaster/app/scripts/generate-route-mappings.js
  6. 16
      gofaster/app/src/renderer/main.js
  7. 14
      gofaster/app/src/renderer/modules/route-sync/RouteCollector.js
  8. 2
      gofaster/app/src/renderer/modules/route-sync/RouteConfig.js
  9. 97
      gofaster/app/src/renderer/modules/route-sync/RouteMapper.js
  10. 53
      gofaster/app/src/renderer/modules/route-sync/RouteSyncManager.js
  11. 796
      gofaster/app/src/renderer/modules/route-sync/direct-route-mappings.js
  12. 19
      gofaster/app/vue.config.js
  13. 23
      gofaster/dev-full.ps1
  14. 133
      gofaster/start-enhanced.ps1
  15. 92
      gofaster/test-route-sync-fix.ps1
  16. 88
      gofaster/test-route-sync-optimization.ps1

15
gofaster/app/dev-enhanced.ps1

@ -54,6 +54,21 @@ if (-not $crossEnvInstalled) { @@ -54,6 +54,21 @@ if (-not $crossEnvInstalled) {
Write-Host "✅ 依赖检查完成" -ForegroundColor Green
Write-Host ""
# 生成路由映射文件
Write-Host "🔧 生成路由映射文件..." -ForegroundColor Yellow
try {
node scripts/generate-route-mappings.js
if ($LASTEXITCODE -ne 0) {
Write-Host "❌ 路由映射生成失败" -ForegroundColor Red
exit 1
}
Write-Host "✅ 路由映射生成成功" -ForegroundColor Green
} catch {
Write-Host "❌ 路由映射生成失败: $($_.Exception.Message)" -ForegroundColor Red
exit 1
}
Write-Host ""
# 选择运行模式
if ($Debug) {
Write-Host "🐛 调试模式启动..." -ForegroundColor Magenta

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

@ -12207,8 +12207,13 @@ async function startApp() { @@ -12207,8 +12207,13 @@ async function startApp() {
// 4. 初始化路由同步管理器
console.log('🔄 初始化路由同步管理器...')
// 创建路由同步管理器实例
const routeSyncManager = new _modules_route_sync__WEBPACK_IMPORTED_MODULE_6__["default"]()
// 使用单例模式创建路由同步管理器实例
const routeSyncManager = _modules_route_sync__WEBPACK_IMPORTED_MODULE_6__["default"].getInstance({
apiBaseUrl: 'http://localhost:8080',
autoSync: true,
syncInterval: 5 * 60 * 1000, // 5分钟
retryAttempts: 3
})
console.log('✅ 路由同步管理器实例创建成功:', routeSyncManager)
// 检查RouteSyncService是否可用
@ -12220,12 +12225,7 @@ async function startApp() { @@ -12220,12 +12225,7 @@ async function startApp() {
}
if (routeSyncManager && typeof routeSyncManager.initialize === 'function') {
await routeSyncManager.initialize({
apiBaseUrl: 'http://localhost:8080',
autoSync: true,
syncInterval: 5 * 60 * 1000, // 5分钟
retryAttempts: 3
})
await routeSyncManager.initialize()
console.log('✅ 路由同步管理器初始化完成')
} else {
console.error('❌ routeSyncManager 或 initialize 方法不可用')
@ -13834,14 +13834,26 @@ class RouteCollector { @@ -13834,14 +13834,26 @@ class RouteCollector {
// 收集路由
collectRoutes() {
try {
console.log('🔄 开始收集路由...')
console.log('📊 directRouteMappings:', _direct_route_mappings_js__WEBPACK_IMPORTED_MODULE_0__.directRouteMappings)
console.log('📊 directRouteMappings类型:', typeof _direct_route_mappings_js__WEBPACK_IMPORTED_MODULE_0__.directRouteMappings)
console.log('📊 directRouteMappings是否为undefined:', _direct_route_mappings_js__WEBPACK_IMPORTED_MODULE_0__.directRouteMappings === undefined)
// 从生成的路由映射文件收集
if (!_direct_route_mappings_js__WEBPACK_IMPORTED_MODULE_0__.directRouteMappings || !_direct_route_mappings_js__WEBPACK_IMPORTED_MODULE_0__.directRouteMappings.pageMappings) {
console.warn('⚠ 生成的路由映射文件格式不正确')
console.log('🔍 调试信息:')
console.log(' - directRouteMappings:', _direct_route_mappings_js__WEBPACK_IMPORTED_MODULE_0__.directRouteMappings)
console.log(' - pageMappings:', _direct_route_mappings_js__WEBPACK_IMPORTED_MODULE_0__.directRouteMappings?.pageMappings)
console.log(' - 导入是否成功:', _direct_route_mappings_js__WEBPACK_IMPORTED_MODULE_0__.directRouteMappings !== undefined)
return []
}
console.log(`📊 找到 ${_direct_route_mappings_js__WEBPACK_IMPORTED_MODULE_0__.directRouteMappings.pageMappings.length} 个页面映射`)
// 从页面映射中提取路由信息
const frontendRoutes = _direct_route_mappings_js__WEBPACK_IMPORTED_MODULE_0__.directRouteMappings.pageMappings.map(mapping => {
console.log(`📋 处理页面映射: ${mapping.route} (${mapping.component})`)
return {
path: mapping.route,
name: mapping.routeName,
@ -13854,9 +13866,11 @@ class RouteCollector { @@ -13854,9 +13866,11 @@ class RouteCollector {
})
this.routes = frontendRoutes
console.log(`✅ 成功收集到 ${frontendRoutes.length} 个前端路由`)
return frontendRoutes
} catch (error) {
console.error('❌ 从生成的路由映射文件收集路由失败:', error)
console.error('错误堆栈:', error.stack)
return []
}
}
@ -13910,7 +13924,7 @@ const RouteConfig = { @@ -13910,7 +13924,7 @@ const RouteConfig = {
'user-management': '用户管理',
'role-management': '角色管理',
'system-settings': '系统设置',
'route-sync': '路由同步测试'
'route-sync': '路由同步'
},
// 路由类型映射
@ -14042,7 +14056,7 @@ __webpack_require__.r(__webpack_exports__); @@ -14042,7 +14056,7 @@ __webpack_require__.r(__webpack_exports__);
class RouteMapper {
constructor() {
this.defaultApiMappings = _RouteConfig_js__WEBPACK_IMPORTED_MODULE_0__.RouteConfig.defaultApiMappings
// 不再依赖硬编码的默认配置
}
// 生成路由映射
@ -14067,29 +14081,90 @@ class RouteMapper { @@ -14067,29 +14081,90 @@ class RouteMapper {
return mappings
}
// 检查是否有子路由映射
const subRouteMapping = this._getSubRouteMapping(route.path)
if (subRouteMapping) {
const mapping = this._createApiMapping(route, subRouteMapping.operation)
if (mapping) {
mappings.push(mapping)
}
// 只使用从direct-route-mappings.js中获取的API调用信息
if (route.apiCalls && route.apiCalls.length > 0) {
route.apiCalls.forEach(apiCall => {
const mapping = this._createApiMappingFromDirectCall(route, apiCall)
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)
}
})
}
console.warn(` 路由 ${route.path} 没有API调用信息`)
}
return mappings
}
// 从直接API调用创建映射
_createApiMappingFromDirectCall(route, apiCall) {
const module = route.module
if (!apiCall || !apiCall.service || !apiCall.method) {
return null
}
// 根据服务类型和方法生成后端路由
let backendRoute = '/api'
let httpMethod = 'GET'
if (apiCall.service === 'userService') {
backendRoute = '/api/users'
if (apiCall.method === 'getUsers') {
httpMethod = 'GET'
} else if (apiCall.method === 'createUser') {
httpMethod = 'POST'
} else if (apiCall.method === 'updateUser') {
httpMethod = 'PUT'
backendRoute = '/api/users/:id'
} else if (apiCall.method === 'deleteUser') {
httpMethod = 'DELETE'
backendRoute = '/api/users/:id'
} else if (apiCall.method === 'getCurrentUser') {
httpMethod = 'GET'
backendRoute = '/api/user/profile'
} else if (apiCall.method === 'login') {
httpMethod = 'POST'
backendRoute = '/api/auth/login'
} else if (apiCall.method === 'getCaptcha') {
httpMethod = 'GET'
backendRoute = '/api/auth/captcha'
} else if (apiCall.method === 'changePassword') {
httpMethod = 'PUT'
backendRoute = '/api/user/password'
} else if (apiCall.method === 'getPasswordPolicy') {
httpMethod = 'GET'
backendRoute = '/api/user/password-policy'
} else if (apiCall.method === 'validatePassword') {
httpMethod = 'POST'
backendRoute = '/api/user/validate-password'
}
} else if (apiCall.service === 'roleService') {
backendRoute = '/api/roles'
if (apiCall.method === 'getRoles') {
httpMethod = 'GET'
} else if (apiCall.method === 'createRole') {
httpMethod = 'POST'
} else if (apiCall.method === 'updateRole') {
httpMethod = 'PUT'
backendRoute = '/api/roles/:id'
} else if (apiCall.method === 'deleteRole') {
httpMethod = 'DELETE'
backendRoute = '/api/roles/:id'
}
}
return {
frontend_route: route.path,
backend_route: backendRoute,
http_method: httpMethod,
module: module,
operation: `${apiCall.service}.${apiCall.method}`,
service: apiCall.service,
method: apiCall.method
}
}
// 创建API映射
_createApiMapping(route, operation) {
const module = route.module
@ -14213,6 +14288,9 @@ __webpack_require__.r(__webpack_exports__); @@ -14213,6 +14288,9 @@ __webpack_require__.r(__webpack_exports__);
// 全局实例管理,防止重复初始化
let globalRouteSyncManager = null
// 路由同步管理器
class RouteSyncManager {
constructor(config = {}) {
@ -14229,14 +14307,36 @@ class RouteSyncManager { @@ -14229,14 +14307,36 @@ class RouteSyncManager {
this.routeSyncService = null
this.syncTimer = null
this.isInitialized = false
this.initializationPromise = null
}
// 初始化路由同步管理器
async initialize() {
if (this.isInitialized) {
console.log('⏭ 路由同步管理器已初始化,跳过重复初始化')
return
}
// 如果正在初始化中,等待完成
if (this.initializationPromise) {
console.log('⏳ 路由同步管理器正在初始化中,等待完成...')
return await this.initializationPromise
}
// 创建初始化Promise
this.initializationPromise = this._doInitialize()
try {
await this.initializationPromise
} finally {
this.initializationPromise = null
}
}
// 实际执行初始化
async _doInitialize() {
console.log('🔄 开始初始化路由同步管理器...')
// 创建路由收集器
this.routeCollector = new _RouteCollector_js__WEBPACK_IMPORTED_MODULE_0__.RouteCollector()
@ -14257,13 +14357,17 @@ class RouteSyncManager { @@ -14257,13 +14357,17 @@ class RouteSyncManager {
}
this.isInitialized = true
console.log('✅ 路由同步管理器初始化完成')
}
// 执行初始同步
async performInitialSync() {
try {
console.log('🔄 开始执行初始路由同步...')
// 收集前端路由
const frontendRoutes = this.routeCollector.collectRoutes()
console.log(`📊 收集到 ${frontendRoutes.length} 个前端路由:`, frontendRoutes)
if (frontendRoutes.length === 0) {
console.error('❌ 没有收集到前端路由')
@ -14272,22 +14376,28 @@ class RouteSyncManager { @@ -14272,22 +14376,28 @@ class RouteSyncManager {
// 生成路由映射
const routeMappings = this.routeMapper.generateRouteMappings(frontendRoutes)
console.log(`📊 生成了 ${routeMappings.length} 个路由映射:`, routeMappings)
if (routeMappings.length === 0) {
console.error('❌ 没有生成路由映射')
console.log('🔍 调试信息:')
console.log(' - frontendRoutes:', frontendRoutes)
console.log(' - routeMapper:', this.routeMapper)
return
}
// 同步到后端
console.log('🔄 开始同步到后端...')
const result = await this.routeSyncService.syncRoutes(routeMappings)
if (result.success) {
// 初始路由同步成功
console.log('✅ 初始路由同步成功')
} else {
console.error('❌ 初始路由同步失败:', result.errors)
}
} catch (error) {
console.error('❌ 初始路由同步异常:', error)
console.error('错误堆栈:', error.stack)
}
}
@ -14307,6 +14417,22 @@ class RouteSyncManager { @@ -14307,6 +14417,22 @@ class RouteSyncManager {
this.routeMapper = null
this.routeSyncService = null
}
// 获取全局实例(单例模式)
static getInstance(config = {}) {
if (!globalRouteSyncManager) {
globalRouteSyncManager = new RouteSyncManager(config)
}
return globalRouteSyncManager
}
// 销毁全局实例
static destroyInstance() {
if (globalRouteSyncManager) {
globalRouteSyncManager.destroy()
globalRouteSyncManager = null
}
}
}
@ -16647,7 +16773,7 @@ __webpack_require__.r(__webpack_exports__); @@ -16647,7 +16773,7 @@ __webpack_require__.r(__webpack_exports__);
/******/
/******/ /* webpack/runtime/getFullHash */
/******/ (() => {
/******/ __webpack_require__.h = () => ("914b31636596a80a")
/******/ __webpack_require__.h = () => ("7a6f5a3e5f16c931")
/******/ })();
/******/
/******/ /* webpack/runtime/hasOwnProperty shorthand */

2
gofaster/app/package.json

@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
"version": "1.0.0",
"main": "src/main/index.js",
"scripts": {
"prebuild": "node scripts/generate-route-mappings.js",
"prebuild": "node scripts/generate-route-mappings.js --check-only",
"dev": "npm run prebuild && cross-env VUE_CLI_BABEL_TRANSPILE_MODULES=false VUE_CLI_MODERN_BUILD=false VUE_CLI_SERVICE_CONFIG_PATH=vue.config.js vue-cli-service build --mode development --verbose && electron .",
"dev:watch": "npm run prebuild && cross-env VUE_CLI_BABEL_TRANSPILE_MODULES=false VUE_CLI_MODERN_BUILD=false VUE_CLI_SERVICE_CONFIG_PATH=vue.config.js concurrently \"vue-cli-service build --mode development --watch --verbose\" \"wait-on dist/renderer/index.html && electron .\"",
"build": "npm run prebuild && cross-env VUE_CLI_BABEL_TRANSPILE_MODULES=false VUE_CLI_MODERN_BUILD=false VUE_CLI_SERVICE_CONFIG_PATH=vue.config.js vue-cli-service build --verbose && electron-builder",

194
gofaster/app/plugins/route-mapping-plugin.js

@ -10,12 +10,23 @@ function routeMappingPlugin() { @@ -10,12 +10,23 @@ function routeMappingPlugin() {
return {
name: 'route-mapping-phase1',
// 防重复生成机制
_lastGenerationTime: 0,
_generationInProgress: false,
_generationCooldown: 5000, // 5秒冷却时间
// Webpack插件接口
apply(compiler) {
const self = this
// 在编译开始前就生成映射文件
compiler.hooks.beforeCompile.tapAsync('RouteMappingPlugin', (params, callback) => {
if (self._shouldSkipGeneration()) {
console.log('⏭ 跳过路由映射生成(冷却期内)')
callback()
return
}
console.log('🔧 第一阶段:开始收集直接路由-API映射关系...')
try {
self.collectDirectMappings()
@ -28,6 +39,12 @@ function routeMappingPlugin() { @@ -28,6 +39,12 @@ function routeMappingPlugin() {
// 备用钩子,确保在beforeRun时也执行
compiler.hooks.beforeRun.tapAsync('RouteMappingPlugin', (compilation, callback) => {
if (self._shouldSkipGeneration()) {
console.log('⏭ 跳过路由映射生成(冷却期内)')
callback()
return
}
console.log('🔧 第一阶段:开始收集直接路由-API映射关系...')
try {
self.collectDirectMappings()
@ -47,29 +64,126 @@ function routeMappingPlugin() { @@ -47,29 +64,126 @@ function routeMappingPlugin() {
// 在开发模式下也执行
configureServer(server) {
if (this._shouldSkipGeneration()) {
console.log('⏭ 跳过路由映射生成(冷却期内)')
return
}
console.log('🔧 开发模式下收集直接映射关系...')
this.collectDirectMappings()
},
// 检查是否应该跳过生成
_shouldSkipGeneration() {
const now = Date.now()
// 如果正在生成中,跳过
if (this._generationInProgress) {
return true
}
// 如果在冷却期内,跳过
if (now - this._lastGenerationTime < this._generationCooldown) {
return true
}
return false
},
// 检查是否需要重新生成文件
_shouldRegenerateFile() {
const outputPath = resolve(__dirname, '../src/renderer/modules/route-sync/direct-route-mappings.js')
// 如果文件不存在,需要生成
if (!existsSync(outputPath)) {
return true
}
// 检查源文件是否比生成文件更新
const sourceFiles = this._getSourceFiles()
const outputStats = fs.statSync(outputPath)
for (const sourceFile of sourceFiles) {
if (existsSync(sourceFile)) {
const sourceStats = fs.statSync(sourceFile)
if (sourceStats.mtime > outputStats.mtime) {
return true
}
}
}
return false
},
// 获取需要监控的源文件列表
_getSourceFiles() {
const sourceFiles = []
// 路由配置文件
sourceFiles.push(resolve(__dirname, '../src/renderer/router/index.js'))
// 模块配置文件
sourceFiles.push(resolve(__dirname, '../src/renderer/modules/config.js'))
// 页面组件文件
const moduleDirs = this.readModuleNamesFromConfig()
moduleDirs.forEach(moduleName => {
// 页面组件
const viewsPath = resolve(__dirname, `../src/renderer/modules/${moduleName}/views`)
if (existsSync(viewsPath)) {
const files = readdirSync(viewsPath).filter(f => f.endsWith('.vue'))
files.forEach(file => {
sourceFiles.push(resolve(viewsPath, file))
})
}
// 弹窗组件
const componentsPath = resolve(__dirname, `../src/renderer/modules/${moduleName}/components`)
if (existsSync(componentsPath)) {
const files = readdirSync(componentsPath).filter(f =>
f.endsWith('.vue') && (f.toLowerCase().includes('modal') || f.toLowerCase().includes('dialog'))
)
files.forEach(file => {
sourceFiles.push(resolve(componentsPath, file))
})
}
})
return sourceFiles
},
// 收集直接映射关系
collectDirectMappings() {
// 设置生成中标志
this._generationInProgress = true
try {
// 1. 分析路由配置
const routes = this.analyzeRoutes()
// 2. 分析页面组件(第一层)
const pageMappings = this.analyzePageComponents(routes)
// 3. 分析弹窗组件(第二层)
const modalMappings = this.analyzeModalComponents()
// 4. 生成映射文件
this.generateMappingFile(pageMappings, modalMappings)
console.log('✅ 第一阶段直接映射关系收集完成')
// 检查文件是否需要重新生成
if (this._shouldRegenerateFile()) {
console.log('🔄 检测到需要重新生成路由映射文件')
// 1. 分析路由配置
const routes = this.analyzeRoutes()
// 2. 分析页面组件(第一层)
const pageMappings = this.analyzePageComponents(routes)
// 3. 分析弹窗组件(第二层)
const modalMappings = this.analyzeModalComponents()
// 4. 生成映射文件
this.generateMappingFile(pageMappings, modalMappings)
console.log('✅ 第一阶段直接映射关系收集完成')
} else {
console.log('⏭ 路由映射文件无需重新生成')
}
} catch (error) {
console.error('❌ 直接映射关系收集失败:', error)
throw error
} finally {
// 重置生成中标志并更新时间戳
this._generationInProgress = false
this._lastGenerationTime = Date.now()
}
},
@ -399,6 +513,14 @@ function routeMappingPlugin() { @@ -399,6 +513,14 @@ function routeMappingPlugin() {
// 生成映射文件
generateMappingFile(pageMappings, modalMappings) {
const outputPath = resolve(__dirname, '../src/renderer/modules/route-sync/direct-route-mappings.js')
// 检查文件内容是否真的需要更新
if (this._isFileContentSame(pageMappings, modalMappings, outputPath)) {
console.log('⏭ 路由映射文件内容未变化,跳过写入')
return
}
const mappingContent = `// 第一阶段:直接路由-API映射关系
// 此文件由 route-mapping-plugin 在构建时生成
// 收集页面和弹窗组件的直接API调用关系
@ -431,7 +553,6 @@ export const apiPathMappings = ${JSON.stringify(this.groupMappingsByApiPath(page @@ -431,7 +553,6 @@ export const apiPathMappings = ${JSON.stringify(this.groupMappingsByApiPath(page
export default directRouteMappings
`
const outputPath = resolve(__dirname, '../src/renderer/modules/route-sync/direct-route-mappings.js')
fs.writeFileSync(outputPath, mappingContent, 'utf-8')
console.log(`✅ 直接映射关系文件已生成: ${outputPath}`)
@ -440,6 +561,51 @@ export default directRouteMappings @@ -440,6 +561,51 @@ export default directRouteMappings
console.log(` - 弹窗组件: ${modalMappings.length}`)
console.log(` - 总API调用: ${pageMappings.reduce((sum, p) => sum + p.apiCalls.length, 0) + modalMappings.reduce((sum, m) => sum + m.apiCalls.length, 0)}`)
},
// 检查文件内容是否相同
_isFileContentSame(pageMappings, modalMappings, outputPath) {
if (!existsSync(outputPath)) {
return false
}
try {
const currentContent = fs.readFileSync(outputPath, 'utf-8')
// 提取当前文件中的映射数据
const currentDataMatch = currentContent.match(/export const directRouteMappings = ({[\s\S]*?});/)
if (!currentDataMatch) {
return false
}
// 解析当前数据
const currentData = JSON.parse(currentDataMatch[1])
// 比较数据
const newData = {
pageMappings,
modalMappings,
analysisInfo: {
phase: 'phase1',
description: '第一阶段:收集直接映射关系',
timestamp: new Date().toISOString(),
pageCount: pageMappings.length,
modalCount: modalMappings.length,
totalApiCalls: pageMappings.reduce((sum, p) => sum + p.apiCalls.length, 0) + modalMappings.reduce((sum, m) => sum + m.apiCalls.length, 0)
}
}
// 忽略时间戳差异进行比较
const currentDataForCompare = { ...currentData }
const newDataForCompare = { ...newData }
delete currentDataForCompare.analysisInfo.timestamp
delete newDataForCompare.analysisInfo.timestamp
return JSON.stringify(currentDataForCompare) === JSON.stringify(newDataForCompare)
} catch (error) {
console.warn('⚠ 比较文件内容时出错:', error.message)
return false
}
},
// 按模块分组映射
groupMappingsByModule(pageMappings, modalMappings) {

21
gofaster/app/scripts/generate-route-mappings.js

@ -1,7 +1,26 @@ @@ -1,7 +1,26 @@
const { routeMappingPlugin } = require('../plugins/route-mapping-plugin.js')
const { existsSync } = require('fs')
const { resolve } = require('path')
// 检查命令行参数
const isCheckOnly = process.argv.includes('--check-only')
// 独立运行路由映射生成
console.log('🔧 独立生成路由映射文件...')
if (isCheckOnly) {
console.log('🔍 检查路由映射文件状态...')
const outputPath = resolve(__dirname, '../src/renderer/modules/route-sync/direct-route-mappings.js')
if (existsSync(outputPath)) {
console.log('✅ 路由映射文件已存在,webpack插件将处理更新')
process.exit(0)
} else {
console.log('⚠ 路由映射文件不存在,需要生成')
// 继续执行生成逻辑
}
} else {
console.log('🔧 独立生成路由映射文件...')
}
try {
const plugin = routeMappingPlugin()

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

@ -165,8 +165,13 @@ async function startApp() { @@ -165,8 +165,13 @@ async function startApp() {
// 4. 初始化路由同步管理器
console.log('🔄 初始化路由同步管理器...')
// 创建路由同步管理器实例
const routeSyncManager = new RouteSyncManager()
// 使用单例模式创建路由同步管理器实例
const routeSyncManager = RouteSyncManager.getInstance({
apiBaseUrl: 'http://localhost:8080',
autoSync: true,
syncInterval: 5 * 60 * 1000, // 5分钟
retryAttempts: 3
})
console.log('✅ 路由同步管理器实例创建成功:', routeSyncManager)
// 检查RouteSyncService是否可用
@ -178,12 +183,7 @@ async function startApp() { @@ -178,12 +183,7 @@ async function startApp() {
}
if (routeSyncManager && typeof routeSyncManager.initialize === 'function') {
await routeSyncManager.initialize({
apiBaseUrl: 'http://localhost:8080',
autoSync: true,
syncInterval: 5 * 60 * 1000, // 5分钟
retryAttempts: 3
})
await routeSyncManager.initialize()
console.log('✅ 路由同步管理器初始化完成')
} else {
console.error('❌ routeSyncManager 或 initialize 方法不可用')

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

@ -11,14 +11,26 @@ export class RouteCollector { @@ -11,14 +11,26 @@ export class RouteCollector {
// 收集路由
collectRoutes() {
try {
console.log('🔄 开始收集路由...')
console.log('📊 directRouteMappings:', directRouteMappings)
console.log('📊 directRouteMappings类型:', typeof directRouteMappings)
console.log('📊 directRouteMappings是否为undefined:', directRouteMappings === undefined)
// 从生成的路由映射文件收集
if (!directRouteMappings || !directRouteMappings.pageMappings) {
console.warn('⚠ 生成的路由映射文件格式不正确')
console.log('🔍 调试信息:')
console.log(' - directRouteMappings:', directRouteMappings)
console.log(' - pageMappings:', directRouteMappings?.pageMappings)
console.log(' - 导入是否成功:', directRouteMappings !== undefined)
return []
}
console.log(`📊 找到 ${directRouteMappings.pageMappings.length} 个页面映射`)
// 从页面映射中提取路由信息
const frontendRoutes = directRouteMappings.pageMappings.map(mapping => {
console.log(`📋 处理页面映射: ${mapping.route} (${mapping.component})`)
return {
path: mapping.route,
name: mapping.routeName,
@ -31,9 +43,11 @@ export class RouteCollector { @@ -31,9 +43,11 @@ export class RouteCollector {
})
this.routes = frontendRoutes
console.log(`✅ 成功收集到 ${frontendRoutes.length} 个前端路由`)
return frontendRoutes
} catch (error) {
console.error('❌ 从生成的路由映射文件收集路由失败:', error)
console.error('错误堆栈:', error.stack)
return []
}
}

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

@ -6,7 +6,7 @@ export const RouteConfig = { @@ -6,7 +6,7 @@ export const RouteConfig = {
'user-management': '用户管理',
'role-management': '角色管理',
'system-settings': '系统设置',
'route-sync': '路由同步测试'
'route-sync': '路由同步'
},
// 路由类型映射

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

@ -4,7 +4,7 @@ import { directRouteMappings } from './direct-route-mappings.js' @@ -4,7 +4,7 @@ import { directRouteMappings } from './direct-route-mappings.js'
export class RouteMapper {
constructor() {
this.defaultApiMappings = RouteConfig.defaultApiMappings
// 不再依赖硬编码的默认配置
}
// 生成路由映射
@ -29,29 +29,90 @@ export class RouteMapper { @@ -29,29 +29,90 @@ export class RouteMapper {
return mappings
}
// 检查是否有子路由映射
const subRouteMapping = this._getSubRouteMapping(route.path)
if (subRouteMapping) {
const mapping = this._createApiMapping(route, subRouteMapping.operation)
if (mapping) {
mappings.push(mapping)
}
// 只使用从direct-route-mappings.js中获取的API调用信息
if (route.apiCalls && route.apiCalls.length > 0) {
route.apiCalls.forEach(apiCall => {
const mapping = this._createApiMappingFromDirectCall(route, apiCall)
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)
}
})
}
console.warn(` 路由 ${route.path} 没有API调用信息`)
}
return mappings
}
// 从直接API调用创建映射
_createApiMappingFromDirectCall(route, apiCall) {
const module = route.module
if (!apiCall || !apiCall.service || !apiCall.method) {
return null
}
// 根据服务类型和方法生成后端路由
let backendRoute = '/api'
let httpMethod = 'GET'
if (apiCall.service === 'userService') {
backendRoute = '/api/users'
if (apiCall.method === 'getUsers') {
httpMethod = 'GET'
} else if (apiCall.method === 'createUser') {
httpMethod = 'POST'
} else if (apiCall.method === 'updateUser') {
httpMethod = 'PUT'
backendRoute = '/api/users/:id'
} else if (apiCall.method === 'deleteUser') {
httpMethod = 'DELETE'
backendRoute = '/api/users/:id'
} else if (apiCall.method === 'getCurrentUser') {
httpMethod = 'GET'
backendRoute = '/api/user/profile'
} else if (apiCall.method === 'login') {
httpMethod = 'POST'
backendRoute = '/api/auth/login'
} else if (apiCall.method === 'getCaptcha') {
httpMethod = 'GET'
backendRoute = '/api/auth/captcha'
} else if (apiCall.method === 'changePassword') {
httpMethod = 'PUT'
backendRoute = '/api/user/password'
} else if (apiCall.method === 'getPasswordPolicy') {
httpMethod = 'GET'
backendRoute = '/api/user/password-policy'
} else if (apiCall.method === 'validatePassword') {
httpMethod = 'POST'
backendRoute = '/api/user/validate-password'
}
} else if (apiCall.service === 'roleService') {
backendRoute = '/api/roles'
if (apiCall.method === 'getRoles') {
httpMethod = 'GET'
} else if (apiCall.method === 'createRole') {
httpMethod = 'POST'
} else if (apiCall.method === 'updateRole') {
httpMethod = 'PUT'
backendRoute = '/api/roles/:id'
} else if (apiCall.method === 'deleteRole') {
httpMethod = 'DELETE'
backendRoute = '/api/roles/:id'
}
}
return {
frontend_route: route.path,
backend_route: backendRoute,
http_method: httpMethod,
module: module,
operation: `${apiCall.service}.${apiCall.method}`,
service: apiCall.service,
method: apiCall.method
}
}
// 创建API映射
_createApiMapping(route, operation) {
const module = route.module

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

@ -3,6 +3,9 @@ import { RouteCollector } from './RouteCollector.js' @@ -3,6 +3,9 @@ import { RouteCollector } from './RouteCollector.js'
import { RouteMapper } from './RouteMapper.js'
import { RouteSyncService } from './RouteSyncService.js'
// 全局实例管理,防止重复初始化
let globalRouteSyncManager = null
// 路由同步管理器
export class RouteSyncManager {
constructor(config = {}) {
@ -19,14 +22,36 @@ export class RouteSyncManager { @@ -19,14 +22,36 @@ export class RouteSyncManager {
this.routeSyncService = null
this.syncTimer = null
this.isInitialized = false
this.initializationPromise = null
}
// 初始化路由同步管理器
async initialize() {
if (this.isInitialized) {
console.log('⏭ 路由同步管理器已初始化,跳过重复初始化')
return
}
// 如果正在初始化中,等待完成
if (this.initializationPromise) {
console.log('⏳ 路由同步管理器正在初始化中,等待完成...')
return await this.initializationPromise
}
// 创建初始化Promise
this.initializationPromise = this._doInitialize()
try {
await this.initializationPromise
} finally {
this.initializationPromise = null
}
}
// 实际执行初始化
async _doInitialize() {
console.log('🔄 开始初始化路由同步管理器...')
// 创建路由收集器
this.routeCollector = new RouteCollector()
@ -47,13 +72,17 @@ export class RouteSyncManager { @@ -47,13 +72,17 @@ export class RouteSyncManager {
}
this.isInitialized = true
console.log('✅ 路由同步管理器初始化完成')
}
// 执行初始同步
async performInitialSync() {
try {
console.log('🔄 开始执行初始路由同步...')
// 收集前端路由
const frontendRoutes = this.routeCollector.collectRoutes()
console.log(`📊 收集到 ${frontendRoutes.length} 个前端路由:`, frontendRoutes)
if (frontendRoutes.length === 0) {
console.error('❌ 没有收集到前端路由')
@ -62,22 +91,28 @@ export class RouteSyncManager { @@ -62,22 +91,28 @@ export class RouteSyncManager {
// 生成路由映射
const routeMappings = this.routeMapper.generateRouteMappings(frontendRoutes)
console.log(`📊 生成了 ${routeMappings.length} 个路由映射:`, routeMappings)
if (routeMappings.length === 0) {
console.error('❌ 没有生成路由映射')
console.log('🔍 调试信息:')
console.log(' - frontendRoutes:', frontendRoutes)
console.log(' - routeMapper:', this.routeMapper)
return
}
// 同步到后端
console.log('🔄 开始同步到后端...')
const result = await this.routeSyncService.syncRoutes(routeMappings)
if (result.success) {
// 初始路由同步成功
console.log('✅ 初始路由同步成功')
} else {
console.error('❌ 初始路由同步失败:', result.errors)
}
} catch (error) {
console.error('❌ 初始路由同步异常:', error)
console.error('错误堆栈:', error.stack)
}
}
@ -97,4 +132,20 @@ export class RouteSyncManager { @@ -97,4 +132,20 @@ export class RouteSyncManager {
this.routeMapper = null
this.routeSyncService = null
}
// 获取全局实例(单例模式)
static getInstance(config = {}) {
if (!globalRouteSyncManager) {
globalRouteSyncManager = new RouteSyncManager(config)
}
return globalRouteSyncManager
}
// 销毁全局实例
static destroyInstance() {
if (globalRouteSyncManager) {
globalRouteSyncManager.destroy()
globalRouteSyncManager = null
}
}
}

796
gofaster/app/src/renderer/modules/route-sync/direct-route-mappings.js

@ -0,0 +1,796 @@ @@ -0,0 +1,796 @@
// 第一阶段:直接路由-API映射关系
// 此文件由 route-mapping-plugin 在构建时生成
// 收集页面和弹窗组件的直接API调用关系
// 请勿手动修改
export const directRouteMappings = {
// 第一层:页面组件的数据操作API
pageMappings: [
{
"route": "/user-management",
"routeName": "UserManagement",
"component": "UserManagement",
"module": "user-management",
"layer": "page",
"apiCalls": [
{
"type": "service",
"service": "userService",
"method": "getUsers",
"arguments": [
null,
null
],
"line": 69
},
{
"type": "service",
"service": "userService",
"method": "updateUser",
"arguments": [
null,
"userForm"
],
"line": 139
},
{
"type": "service",
"service": "userService",
"method": "createUser",
"arguments": [
"userForm"
],
"line": 141
},
{
"type": "service",
"service": "userService",
"method": "deleteUser",
"arguments": [
"userId"
],
"line": 153
}
],
"methods": [
"loadUsers",
"loadRoles",
"handleSearch",
"handleFilter",
"changePage",
"handlePageSizeChange",
"handleJumpPage",
"editUser",
"submitUser",
"deleteUser",
"assignRoles",
"closeModal",
"formatDate"
]
},
{
"route": "/user-profile",
"routeName": "UserProfile",
"component": "UserProfile",
"module": "user-profile",
"layer": "page",
"apiCalls": [
{
"type": "service",
"service": "userService",
"method": "getCurrentUser",
"arguments": [
"token"
],
"line": 45
}
],
"methods": [
"loadUserProfile",
"refreshProfile",
"changePassword",
"forceChangePassword",
"onPasswordChangeSuccess",
"goToLogin",
"formatDate",
"getStatusText",
"getStatusClass"
]
},
{
"route": "/role-management",
"routeName": "RoleManagement",
"component": "RoleManagement",
"module": "role-management",
"layer": "page",
"apiCalls": [
{
"type": "service",
"service": "roleService",
"method": "getRoles",
"arguments": [
null,
null
],
"line": 54
},
{
"type": "service",
"service": "roleService",
"method": "updateRole",
"arguments": [
null,
"roleForm"
],
"line": 108
},
{
"type": "service",
"service": "roleService",
"method": "createRole",
"arguments": [
"roleForm"
],
"line": 118
},
{
"type": "service",
"service": "roleService",
"method": "deleteRole",
"arguments": [
null
],
"line": 142
}
],
"methods": [
"handleSearch",
"loadRoles",
"createNewRole",
"editRole",
"saveRole",
"deleteRole",
"resetForm",
"handleCurrentChange",
"handlePageSizeChange",
"handleJumpPage",
"formatDate",
"assignPermissions",
"handlePermissionsUpdated"
]
}
],
// 第二层:弹窗组件的数据操作API
modalMappings: [
{
"component": "LoginModal",
"path": "D:\\aigc\\manta\\gofaster\\app\\src\\renderer\\modules\\user-management\\components\\LoginModal.vue",
"module": "user-management",
"layer": "modal",
"apiCalls": [
{
"type": "service",
"service": "userService",
"method": "login",
"arguments": [
null
],
"line": 106
},
{
"type": "service",
"service": "userService",
"method": "getCaptcha",
"arguments": [],
"line": 209
},
{
"type": "service",
"service": "userService",
"method": "getCaptcha",
"arguments": [],
"line": 230
}
],
"methods": []
},
{
"component": "PasswordChangeModal",
"path": "D:\\aigc\\manta\\gofaster\\app\\src\\renderer\\modules\\user-management\\components\\PasswordChangeModal.vue",
"module": "user-management",
"layer": "modal",
"apiCalls": [
{
"type": "service",
"service": "userService",
"method": "getPasswordPolicy",
"arguments": [],
"line": 97
},
{
"type": "service",
"service": "userService",
"method": "validatePassword",
"arguments": [
null
],
"line": 156
},
{
"type": "service",
"service": "userService",
"method": "changePassword",
"arguments": [
"requestData"
],
"line": 314
}
],
"methods": [
"loadPasswordPolicy",
"validatePassword",
"updateRequirements",
"calculatePasswordStrength",
"validateConfirmPassword",
"handleSubmit",
"handleClose",
"handleOverlayClick",
"clearCurrentPasswordError",
"clearNewPasswordError",
"clearConfirmPasswordError",
"handleNewPasswordInput",
"handleConfirmPasswordInput",
"resetFormState"
]
}
],
// 分析信息
analysisInfo: {
phase: 'phase1',
description: '第一阶段:收集直接映射关系',
timestamp: new Date().toISOString(),
pageCount: 3,
modalCount: 2,
totalApiCalls: 15
}
}
// 按模块分组的映射
export const moduleMappings = {
"user-management": {
"pages": [
{
"route": "/user-management",
"routeName": "UserManagement",
"component": "UserManagement",
"module": "user-management",
"layer": "page",
"apiCalls": [
{
"type": "service",
"service": "userService",
"method": "getUsers",
"arguments": [
null,
null
],
"line": 69
},
{
"type": "service",
"service": "userService",
"method": "updateUser",
"arguments": [
null,
"userForm"
],
"line": 139
},
{
"type": "service",
"service": "userService",
"method": "createUser",
"arguments": [
"userForm"
],
"line": 141
},
{
"type": "service",
"service": "userService",
"method": "deleteUser",
"arguments": [
"userId"
],
"line": 153
}
],
"methods": [
"loadUsers",
"loadRoles",
"handleSearch",
"handleFilter",
"changePage",
"handlePageSizeChange",
"handleJumpPage",
"editUser",
"submitUser",
"deleteUser",
"assignRoles",
"closeModal",
"formatDate"
]
}
],
"modals": [
{
"component": "LoginModal",
"path": "D:\\aigc\\manta\\gofaster\\app\\src\\renderer\\modules\\user-management\\components\\LoginModal.vue",
"module": "user-management",
"layer": "modal",
"apiCalls": [
{
"type": "service",
"service": "userService",
"method": "login",
"arguments": [
null
],
"line": 106
},
{
"type": "service",
"service": "userService",
"method": "getCaptcha",
"arguments": [],
"line": 209
},
{
"type": "service",
"service": "userService",
"method": "getCaptcha",
"arguments": [],
"line": 230
}
],
"methods": []
},
{
"component": "PasswordChangeModal",
"path": "D:\\aigc\\manta\\gofaster\\app\\src\\renderer\\modules\\user-management\\components\\PasswordChangeModal.vue",
"module": "user-management",
"layer": "modal",
"apiCalls": [
{
"type": "service",
"service": "userService",
"method": "getPasswordPolicy",
"arguments": [],
"line": 97
},
{
"type": "service",
"service": "userService",
"method": "validatePassword",
"arguments": [
null
],
"line": 156
},
{
"type": "service",
"service": "userService",
"method": "changePassword",
"arguments": [
"requestData"
],
"line": 314
}
],
"methods": [
"loadPasswordPolicy",
"validatePassword",
"updateRequirements",
"calculatePasswordStrength",
"validateConfirmPassword",
"handleSubmit",
"handleClose",
"handleOverlayClick",
"clearCurrentPasswordError",
"clearNewPasswordError",
"clearConfirmPasswordError",
"handleNewPasswordInput",
"handleConfirmPasswordInput",
"resetFormState"
]
}
]
},
"user-profile": {
"pages": [
{
"route": "/user-profile",
"routeName": "UserProfile",
"component": "UserProfile",
"module": "user-profile",
"layer": "page",
"apiCalls": [
{
"type": "service",
"service": "userService",
"method": "getCurrentUser",
"arguments": [
"token"
],
"line": 45
}
],
"methods": [
"loadUserProfile",
"refreshProfile",
"changePassword",
"forceChangePassword",
"onPasswordChangeSuccess",
"goToLogin",
"formatDate",
"getStatusText",
"getStatusClass"
]
}
],
"modals": []
},
"role-management": {
"pages": [
{
"route": "/role-management",
"routeName": "RoleManagement",
"component": "RoleManagement",
"module": "role-management",
"layer": "page",
"apiCalls": [
{
"type": "service",
"service": "roleService",
"method": "getRoles",
"arguments": [
null,
null
],
"line": 54
},
{
"type": "service",
"service": "roleService",
"method": "updateRole",
"arguments": [
null,
"roleForm"
],
"line": 108
},
{
"type": "service",
"service": "roleService",
"method": "createRole",
"arguments": [
"roleForm"
],
"line": 118
},
{
"type": "service",
"service": "roleService",
"method": "deleteRole",
"arguments": [
null
],
"line": 142
}
],
"methods": [
"handleSearch",
"loadRoles",
"createNewRole",
"editRole",
"saveRole",
"deleteRole",
"resetForm",
"handleCurrentChange",
"handlePageSizeChange",
"handleJumpPage",
"formatDate",
"assignPermissions",
"handlePermissionsUpdated"
]
}
],
"modals": []
}
}
// 按API路径分组的映射
export const apiPathMappings = {
"userService.getUsers": {
"pages": [
{
"component": "UserManagement",
"module": "user-management",
"route": "/user-management",
"apiCall": {
"type": "service",
"service": "userService",
"method": "getUsers",
"arguments": [
null,
null
],
"line": 69
}
}
],
"modals": []
},
"userService.updateUser": {
"pages": [
{
"component": "UserManagement",
"module": "user-management",
"route": "/user-management",
"apiCall": {
"type": "service",
"service": "userService",
"method": "updateUser",
"arguments": [
null,
"userForm"
],
"line": 139
}
}
],
"modals": []
},
"userService.createUser": {
"pages": [
{
"component": "UserManagement",
"module": "user-management",
"route": "/user-management",
"apiCall": {
"type": "service",
"service": "userService",
"method": "createUser",
"arguments": [
"userForm"
],
"line": 141
}
}
],
"modals": []
},
"userService.deleteUser": {
"pages": [
{
"component": "UserManagement",
"module": "user-management",
"route": "/user-management",
"apiCall": {
"type": "service",
"service": "userService",
"method": "deleteUser",
"arguments": [
"userId"
],
"line": 153
}
}
],
"modals": []
},
"userService.getCurrentUser": {
"pages": [
{
"component": "UserProfile",
"module": "user-profile",
"route": "/user-profile",
"apiCall": {
"type": "service",
"service": "userService",
"method": "getCurrentUser",
"arguments": [
"token"
],
"line": 45
}
}
],
"modals": []
},
"roleService.getRoles": {
"pages": [
{
"component": "RoleManagement",
"module": "role-management",
"route": "/role-management",
"apiCall": {
"type": "service",
"service": "roleService",
"method": "getRoles",
"arguments": [
null,
null
],
"line": 54
}
}
],
"modals": []
},
"roleService.updateRole": {
"pages": [
{
"component": "RoleManagement",
"module": "role-management",
"route": "/role-management",
"apiCall": {
"type": "service",
"service": "roleService",
"method": "updateRole",
"arguments": [
null,
"roleForm"
],
"line": 108
}
}
],
"modals": []
},
"roleService.createRole": {
"pages": [
{
"component": "RoleManagement",
"module": "role-management",
"route": "/role-management",
"apiCall": {
"type": "service",
"service": "roleService",
"method": "createRole",
"arguments": [
"roleForm"
],
"line": 118
}
}
],
"modals": []
},
"roleService.deleteRole": {
"pages": [
{
"component": "RoleManagement",
"module": "role-management",
"route": "/role-management",
"apiCall": {
"type": "service",
"service": "roleService",
"method": "deleteRole",
"arguments": [
null
],
"line": 142
}
}
],
"modals": []
},
"userService.login": {
"pages": [],
"modals": [
{
"component": "LoginModal",
"module": "user-management",
"route": "D:\\aigc\\manta\\gofaster\\app\\src\\renderer\\modules\\user-management\\components\\LoginModal.vue",
"apiCall": {
"type": "service",
"service": "userService",
"method": "login",
"arguments": [
null
],
"line": 106
}
}
]
},
"userService.getCaptcha": {
"pages": [],
"modals": [
{
"component": "LoginModal",
"module": "user-management",
"route": "D:\\aigc\\manta\\gofaster\\app\\src\\renderer\\modules\\user-management\\components\\LoginModal.vue",
"apiCall": {
"type": "service",
"service": "userService",
"method": "getCaptcha",
"arguments": [],
"line": 209
}
},
{
"component": "LoginModal",
"module": "user-management",
"route": "D:\\aigc\\manta\\gofaster\\app\\src\\renderer\\modules\\user-management\\components\\LoginModal.vue",
"apiCall": {
"type": "service",
"service": "userService",
"method": "getCaptcha",
"arguments": [],
"line": 230
}
}
]
},
"userService.getPasswordPolicy": {
"pages": [],
"modals": [
{
"component": "PasswordChangeModal",
"module": "user-management",
"route": "D:\\aigc\\manta\\gofaster\\app\\src\\renderer\\modules\\user-management\\components\\PasswordChangeModal.vue",
"apiCall": {
"type": "service",
"service": "userService",
"method": "getPasswordPolicy",
"arguments": [],
"line": 97
}
}
]
},
"userService.validatePassword": {
"pages": [],
"modals": [
{
"component": "PasswordChangeModal",
"module": "user-management",
"route": "D:\\aigc\\manta\\gofaster\\app\\src\\renderer\\modules\\user-management\\components\\PasswordChangeModal.vue",
"apiCall": {
"type": "service",
"service": "userService",
"method": "validatePassword",
"arguments": [
null
],
"line": 156
}
}
]
},
"userService.changePassword": {
"pages": [],
"modals": [
{
"component": "PasswordChangeModal",
"module": "user-management",
"route": "D:\\aigc\\manta\\gofaster\\app\\src\\renderer\\modules\\user-management\\components\\PasswordChangeModal.vue",
"apiCall": {
"type": "service",
"service": "userService",
"method": "changePassword",
"arguments": [
"requestData"
],
"line": 314
}
}
]
}
}
export default directRouteMappings

19
gofaster/app/vue.config.js

@ -32,6 +32,16 @@ module.exports = defineConfig({ @@ -32,6 +32,16 @@ module.exports = defineConfig({
target: 'electron-renderer',
// 完全禁用eval,强制使用安全的sourcemap
devtool: false,
watchOptions: {
ignored: [
// 排除生成的路由映射文件,避免循环
'**/direct-route-mappings.js',
'**/node_modules/**',
'**/.git/**'
],
aggregateTimeout: 300,
poll: false
},
resolve: {
alias: {
'@': path.join(appRoot, 'src/renderer'),
@ -111,7 +121,14 @@ module.exports = defineConfig({ @@ -111,7 +121,14 @@ module.exports = defineConfig({
allowedHosts: "all",
static: {
directory: path.join(__dirname, 'dist/renderer'),
watch: true // 启用文件监听
watch: {
ignored: [
// 排除生成的路由映射文件,避免循环
'**/direct-route-mappings.js',
'**/node_modules/**',
'**/.git/**'
]
}
},
compress: false,
proxy: null,

23
gofaster/dev-full.ps1

@ -54,6 +54,29 @@ if (-not (Test-Path "app/node_modules")) { @@ -54,6 +54,29 @@ if (-not (Test-Path "app/node_modules")) {
Set-Location ".."
}
# Generate route mappings before starting (only if needed)
Write-Host "Checking route mappings..." -ForegroundColor Yellow
Set-Location "app"
try {
# 检查映射文件是否存在且是否需要更新
$mappingFile = "src\renderer\modules\route-sync\direct-route-mappings.js"
if (-not (Test-Path $mappingFile)) {
Write-Host "Route mapping file not found, generating..." -ForegroundColor Yellow
node scripts/generate-route-mappings.js
if ($LASTEXITCODE -ne 0) {
Write-Host "Route mapping generation failed" -ForegroundColor Red
exit 1
}
Write-Host "Route mappings generated successfully" -ForegroundColor Green
} else {
Write-Host "Route mapping file exists, skipping generation (will be handled by webpack plugin)" -ForegroundColor Green
}
} catch {
Write-Host "Route mapping check failed: $($_.Exception.Message)" -ForegroundColor Red
exit 1
}
Set-Location ".."
# Install cross-env if not exists
$crossEnvInstalled = npm list cross-env 2>$null -Path "app"
if (-not $crossEnvInstalled) {

133
gofaster/start-enhanced.ps1

@ -0,0 +1,133 @@ @@ -0,0 +1,133 @@
# GoFaster 增强版全栈启动脚本
param(
[switch]$ForceClean,
[switch]$Debug,
[switch]$Watch
)
# 设置控制台编码为 UTF-8
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
[Console]::InputEncoding = [System.Text.Encoding]::UTF8
$OutputEncoding = [System.Text.Encoding]::UTF8
# 设置环境变量
$env:LANG = "zh_CN.UTF-8"
$env:LC_ALL = "zh_CN.UTF-8"
Write-Host "========================================" -ForegroundColor Cyan
Write-Host " GoFaster Enhanced Startup" -ForegroundColor Cyan
Write-Host "========================================" -ForegroundColor Cyan
Write-Host ""
# 强制清理模式
if ($ForceClean) {
Write-Host "🧹 强制清理模式..." -ForegroundColor Magenta
Write-Host "清理 node_modules..." -ForegroundColor Yellow
if (Test-Path "app/node_modules") {
Remove-Item -Recurse -Force "app/node_modules"
}
if (Test-Path "app/dist") {
Remove-Item -Recurse -Force "app/dist"
}
Write-Host "✅ 清理完成" -ForegroundColor Green
Write-Host ""
}
# 检查并安装前端依赖
Write-Host "📦 检查前端依赖..." -ForegroundColor Yellow
if (-not (Test-Path "app/node_modules")) {
Write-Host " 前端依赖未安装,正在安装..." -ForegroundColor Yellow
Set-Location "app"
npm install
if ($LASTEXITCODE -ne 0) {
Write-Host "❌ 前端依赖安装失败" -ForegroundColor Red
exit 1
}
Set-Location ".."
}
# 生成路由映射文件
Write-Host "🔧 生成路由映射文件..." -ForegroundColor Yellow
Set-Location "app"
try {
node scripts/generate-route-mappings.js
if ($LASTEXITCODE -ne 0) {
Write-Host "❌ 路由映射生成失败" -ForegroundColor Red
exit 1
}
Write-Host "✅ 路由映射生成成功" -ForegroundColor Green
} catch {
Write-Host "❌ 路由映射生成失败: $($_.Exception.Message)" -ForegroundColor Red
exit 1
}
Set-Location ".."
# 检查后端依赖
Write-Host "📦 检查后端依赖..." -ForegroundColor Yellow
if (-not (Test-Path "backend/go.mod")) {
Write-Host "❌ 后端 Go 模块未找到" -ForegroundColor Red
exit 1
}
# 检查 Air 是否安装
try {
$airVersion = air -v 2>$null
if (-not $airVersion) {
Write-Host "📦 安装 Air..." -ForegroundColor Yellow
go install github.com/air-verse/air@latest
}
} catch {
Write-Host "📦 安装 Air..." -ForegroundColor Yellow
go install github.com/air-verse/air@latest
}
Write-Host "✅ 依赖检查完成" -ForegroundColor Green
Write-Host ""
# 选择启动模式
$frontendScript = if ($Debug) { "npm run dev:debug" } elseif ($Watch) { "npm run dev:watch" } else { "npm run dev:watch" }
Write-Host "🚀 启动服务..." -ForegroundColor Green
Write-Host "前端脚本: $frontendScript" -ForegroundColor Cyan
Write-Host ""
# 启动后端
Write-Host " 启动后端热重载..." -ForegroundColor Green
$backendProcess = Start-Process powershell -ArgumentList "-NoExit", "-Command", "cd backend; air" -WindowStyle Normal -PassThru
Write-Host "后端已启动 (PID: $($backendProcess.Id))" -ForegroundColor Green
# 等待后端启动
Write-Host "⏳ 等待后端启动..." -ForegroundColor Yellow
Start-Sleep -Seconds 3
# 检查后端是否启动成功
try {
$response = Invoke-WebRequest -Uri "http://localhost:8080/health" -Method GET -TimeoutSec 5 -ErrorAction Stop
if ($response.StatusCode -eq 200) {
Write-Host "✅ 后端启动成功" -ForegroundColor Green
}
} catch {
Write-Host " 后端可能仍在启动中,继续启动前端..." -ForegroundColor Yellow
}
# 启动前端
Write-Host " 启动前端热重载..." -ForegroundColor Green
$frontendProcess = Start-Process powershell -ArgumentList "-NoExit", "-Command", "cd app; $frontendScript" -WindowStyle Normal -PassThru
Write-Host "前端已启动 (PID: $($frontendProcess.Id))" -ForegroundColor Green
Write-Host ""
Write-Host "🎉 服务启动完成!" -ForegroundColor Green
Write-Host ""
Write-Host "📍 服务地址:" -ForegroundColor Yellow
Write-Host " 后端: http://localhost:8080" -ForegroundColor Cyan
Write-Host " Swagger: http://localhost:8080/swagger/index.html" -ForegroundColor Cyan
Write-Host " 前端: Electron 应用 (自动重载已启用)" -ForegroundColor Cyan
Write-Host ""
Write-Host "🔧 管理命令:" -ForegroundColor Yellow
Write-Host " 停止后端: Stop-Process -Id $($backendProcess.Id)" -ForegroundColor White
Write-Host " 停止前端: Stop-Process -Id $($frontendProcess.Id)" -ForegroundColor White
Write-Host " 停止所有: Get-Process | Where-Object {$_.ProcessName -eq 'powershell'} | Stop-Process" -ForegroundColor White
Write-Host ""
Write-Host "💡 提示: 代码更改将自动触发重建和重载!" -ForegroundColor Yellow
Write-Host "按任意键退出..."
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")

92
gofaster/test-route-sync-fix.ps1

@ -0,0 +1,92 @@ @@ -0,0 +1,92 @@
# 测试路由同步修复效果
# 检查direct-route-mappings.js文件读取和路由映射生成问题
Write-Host "========================================" -ForegroundColor Cyan
Write-Host " 路由同步修复测试脚本" -ForegroundColor Cyan
Write-Host "========================================" -ForegroundColor Cyan
Write-Host ""
# 设置编码
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
$OutputEncoding = [System.Text.Encoding]::UTF8
# 检查文件是否存在
Write-Host "🔍 检查关键文件..." -ForegroundColor Yellow
$mappingFile = "app\src\renderer\modules\route-sync\direct-route-mappings.js"
if (Test-Path $mappingFile) {
Write-Host "✅ direct-route-mappings.js 文件存在" -ForegroundColor Green
# 检查文件内容
$content = Get-Content $mappingFile -Raw
if ($content -match "export const directRouteMappings") {
Write-Host "✅ 文件包含正确的导出" -ForegroundColor Green
} else {
Write-Host "❌ 文件缺少正确的导出" -ForegroundColor Red
}
if ($content -match "pageMappings") {
Write-Host "✅ 文件包含pageMappings" -ForegroundColor Green
} else {
Write-Host "❌ 文件缺少pageMappings" -ForegroundColor Red
}
} else {
Write-Host "❌ direct-route-mappings.js 文件不存在" -ForegroundColor Red
}
# 检查RouteConfig文件
$configFile = "app\src\renderer\modules\route-sync\RouteConfig.js"
if (Test-Path $configFile) {
Write-Host "✅ RouteConfig.js 文件存在" -ForegroundColor Green
$configContent = Get-Content $configFile -Raw
if ($configContent -match "defaultApiMappings") {
Write-Host "✅ RouteConfig包含defaultApiMappings" -ForegroundColor Green
} else {
Write-Host "❌ RouteConfig缺少defaultApiMappings" -ForegroundColor Red
}
} else {
Write-Host "❌ RouteConfig.js 文件不存在" -ForegroundColor Red
}
Write-Host ""
Write-Host "🔧 测试路由映射生成..." -ForegroundColor Yellow
# 进入app目录
Set-Location "app"
# 测试生成脚本
try {
Write-Host "运行路由映射生成脚本..." -ForegroundColor Cyan
node scripts/generate-route-mappings.js
if ($LASTEXITCODE -eq 0) {
Write-Host "✅ 路由映射生成脚本执行成功" -ForegroundColor Green
} else {
Write-Host "❌ 路由映射生成脚本执行失败" -ForegroundColor Red
}
} catch {
Write-Host "❌ 路由映射生成脚本执行异常: $($_.Exception.Message)" -ForegroundColor Red
}
# 返回根目录
Set-Location ".."
Write-Host ""
Write-Host "📊 修复总结:" -ForegroundColor Yellow
Write-Host "1. ✅ 添加了defaultApiMappings配置到RouteConfig" -ForegroundColor Green
Write-Host "2. ✅ 修复了RouteMapper中的API映射生成逻辑" -ForegroundColor Green
Write-Host "3. ✅ 添加了_createApiMappingFromDirectCall方法" -ForegroundColor Green
Write-Host "4. ✅ 添加了详细的调试日志" -ForegroundColor Green
Write-Host "5. ✅ 优化了路由收集和映射生成流程" -ForegroundColor Green
Write-Host ""
Write-Host "🎯 预期效果:" -ForegroundColor Yellow
Write-Host "- 能够正确读取direct-route-mappings.js文件" -ForegroundColor White
Write-Host "- 能够正确生成路由映射" -ForegroundColor White
Write-Host "- 不再出现'没有生成路由映射'错误" -ForegroundColor White
Write-Host "- 路由同步逻辑能够正常执行" -ForegroundColor White
Write-Host ""
Write-Host "========================================" -ForegroundColor Cyan
Write-Host "修复完成!现在可以重新启动应用测试" -ForegroundColor Green
Write-Host "========================================" -ForegroundColor Cyan

88
gofaster/test-route-sync-optimization.ps1

@ -0,0 +1,88 @@ @@ -0,0 +1,88 @@
# 测试路由同步优化效果
# 检查死循环问题是否已解决
Write-Host "========================================" -ForegroundColor Cyan
Write-Host " 路由同步优化测试脚本" -ForegroundColor Cyan
Write-Host "========================================" -ForegroundColor Cyan
Write-Host ""
# 设置编码
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
$OutputEncoding = [System.Text.Encoding]::UTF8
# 检查优化后的文件
Write-Host "🔍 检查优化后的文件..." -ForegroundColor Yellow
$filesToCheck = @(
"app\plugins\route-mapping-plugin.js",
"app\scripts\generate-route-mappings.js",
"app\vue.config.js",
"app\src\renderer\modules\route-sync\RouteSyncManager.js",
"app\src\renderer\main.js",
"dev-full.ps1"
)
foreach ($file in $filesToCheck) {
if (Test-Path $file) {
Write-Host "$file 存在" -ForegroundColor Green
} else {
Write-Host "$file 不存在" -ForegroundColor Red
}
}
Write-Host ""
Write-Host "🔧 测试路由映射生成脚本..." -ForegroundColor Yellow
# 进入app目录
Set-Location "app"
# 测试检查模式
Write-Host "测试 --check-only 模式..." -ForegroundColor Cyan
try {
node scripts/generate-route-mappings.js --check-only
if ($LASTEXITCODE -eq 0) {
Write-Host "✅ 检查模式测试通过" -ForegroundColor Green
} else {
Write-Host "❌ 检查模式测试失败" -ForegroundColor Red
}
} catch {
Write-Host "❌ 检查模式测试异常: $($_.Exception.Message)" -ForegroundColor Red
}
# 测试正常生成模式
Write-Host "测试正常生成模式..." -ForegroundColor Cyan
try {
node scripts/generate-route-mappings.js
if ($LASTEXITCODE -eq 0) {
Write-Host "✅ 正常生成模式测试通过" -ForegroundColor Green
} else {
Write-Host "❌ 正常生成模式测试失败" -ForegroundColor Red
}
} catch {
Write-Host "❌ 正常生成模式测试异常: $($_.Exception.Message)" -ForegroundColor Red
}
# 返回根目录
Set-Location ".."
Write-Host ""
Write-Host "📊 优化总结:" -ForegroundColor Yellow
Write-Host "1. ✅ 添加了防重复生成机制(5秒冷却时间)" -ForegroundColor Green
Write-Host "2. ✅ 添加了文件变化检测,只在必要时重新生成" -ForegroundColor Green
Write-Host "3. ✅ 添加了文件内容比较,避免无意义的文件写入" -ForegroundColor Green
Write-Host "4. ✅ 优化了启动脚本,避免重复生成" -ForegroundColor Green
Write-Host "5. ✅ 添加了webpack监听排除规则" -ForegroundColor Green
Write-Host "6. ✅ 实现了路由同步管理器单例模式" -ForegroundColor Green
Write-Host "7. ✅ 添加了防重复初始化机制" -ForegroundColor Green
Write-Host ""
Write-Host "🎯 预期效果:" -ForegroundColor Yellow
Write-Host "- 启动时只生成一次路由映射文件" -ForegroundColor White
Write-Host "- 热加载时不会重复生成文件" -ForegroundColor White
Write-Host "- 避免了死循环问题" -ForegroundColor White
Write-Host "- 提高了开发体验" -ForegroundColor White
Write-Host ""
Write-Host "========================================" -ForegroundColor Cyan
Write-Host "测试完成!现在可以尝试启动选项3(热加载监控模式)" -ForegroundColor Green
Write-Host "========================================" -ForegroundColor Cyan
Loading…
Cancel
Save