import { resolve } from 'path' import fs from 'fs' // 路由映射插件 export function routeMappingPlugin() { return { name: 'route-mapping', // 在构建开始时执行 buildStart() { console.log('🔧 开始分析路由结构...') this.analyzeRoutes() }, // 在开发模式下也执行 configureServer(server) { console.log('🔧 开发模式下分析路由结构...') this.analyzeRoutes() }, // 分析路由结构 analyzeRoutes() { try { const routerPath = resolve(__dirname, '../src/renderer/router/index.js') const routerContent = fs.readFileSync(routerPath, 'utf-8') // 解析路由配置 const routes = this.parseRoutes(routerContent) // 生成主入口路由映射 const mainRoutes = this.generateMainRoutes(routes) // 从实际服务文件中提取API映射 const moduleApiMappings = this.extractApiMappingsFromServices() // 生成路由映射文件 this.generateRouteMappingFile(mainRoutes, moduleApiMappings) console.log('✅ 路由映射分析完成') } catch (error) { console.error('❌ 路由映射分析失败:', error) } }, // 从实际服务文件中提取API映射 extractApiMappingsFromServices() { const mappings = {} // 用户管理服务 const userServicePath = resolve(__dirname, '../src/renderer/modules/user-management/services/userService.js') console.log('🔍 检查用户服务文件路径:', userServicePath) if (fs.existsSync(userServicePath)) { console.log('✅ 找到用户服务文件') const userServiceContent = fs.readFileSync(userServicePath, 'utf-8') mappings['user-management'] = this.parseServiceFile(userServiceContent, 'user-management') } else { console.log('❌ 未找到用户服务文件') } // 角色管理服务 const roleServicePath = resolve(__dirname, '../src/renderer/modules/role-management/services/roleService.js') console.log('🔍 检查角色服务文件路径:', roleServicePath) if (fs.existsSync(roleServicePath)) { console.log('✅ 找到角色服务文件') const roleServiceContent = fs.readFileSync(roleServicePath, 'utf-8') mappings['role-management'] = this.parseServiceFile(roleServiceContent, 'role-management') } else { console.log('❌ 未找到角色服务文件') } // 系统设置服务(如果存在) const settingsServicePath = resolve(__dirname, '../src/renderer/modules/system-settings/services/settingsService.js') console.log('🔍 检查系统设置服务文件路径:', settingsServicePath) if (fs.existsSync(settingsServicePath)) { console.log('✅ 找到系统设置服务文件') const settingsServiceContent = fs.readFileSync(settingsServicePath, 'utf-8') mappings['system-settings'] = this.parseServiceFile(settingsServiceContent, 'system-settings') } else { console.log('❌ 未找到系统设置服务文件') } console.log('🔍 从服务文件中提取的API映射:', mappings) return mappings }, // 解析服务文件中的API调用 parseServiceFile(content, moduleName) { const operations = {} console.log(`🔍 开始解析模块 "${moduleName}" 的服务文件...`) // 匹配 api.get, api.post, api.put, api.delete 调用 const apiCallRegex = /api\.(get|post|put|delete|patch)\s*\(\s*['"`]([^'"`]+)['"`]/g let match let matchCount = 0 while ((match = apiCallRegex.exec(content)) !== null) { const method = match[1].toUpperCase() const path = match[2] matchCount++ console.log(`🔍 找到API调用 ${matchCount}: ${method} ${path}`) // 根据路径和方法推断操作类型 const operation = this.inferOperationFromPath(path, method) if (operation) { operations[operation] = { path: path, method: method } console.log(`✅ 映射操作: ${operation} -> ${method} ${path}`) } } console.log(`📊 模块 "${moduleName}" 找到 ${matchCount} 个API调用,映射了 ${Object.keys(operations).length} 个操作`) // 如果没有找到任何API调用,使用默认配置 if (Object.keys(operations).length === 0) { console.log(`⚠️ 模块 "${moduleName}" 未找到API调用,使用默认配置`) return this.getDefaultApiMapping(moduleName) } // 提取basePath(取第一个路径的共同前缀) const basePath = this.extractBasePath(Object.values(operations).map(op => op.path)) console.log(`🔍 提取的basePath: ${basePath}`) return { basePath: basePath, operations: operations } }, // 从路径推断操作类型 inferOperationFromPath(path, method) { const pathLower = path.toLowerCase() // 根据路径模式推断操作 if (path.includes('/:id') || path.includes('/{id}')) { if (method === 'GET') return 'detail' if (method === 'PUT') return 'update' if (method === 'DELETE') return 'delete' } if (path.includes('/search')) return 'search' if (path.includes('/filter')) return 'filter' if (path.includes('/roles')) return 'getRoles' if (path.includes('/permissions')) return 'getPermissions' if (path.includes('/assign')) return 'assignRoles' if (path.includes('/remove')) return 'removeRoles' if (path.includes('/enable')) return 'enable' if (path.includes('/disable')) return 'disable' if (path.includes('/change-password')) return 'changePassword' if (path.includes('/password-policy')) return 'getPasswordPolicy' if (path.includes('/validate-password')) return 'validatePassword' if (path.includes('/password-status')) return 'checkPasswordStatus' if (path.includes('/captcha')) return 'getCaptcha' if (path.includes('/login')) return 'login' if (path.includes('/logout')) return 'logout' if (path.includes('/current-user')) return 'getCurrentUser' // 根据HTTP方法推断 if (method === 'GET' && !path.includes('/')) return 'list' if (method === 'POST' && !path.includes('/')) return 'create' if (method === 'PUT' && !path.includes('/')) return 'update' if (method === 'DELETE' && !path.includes('/')) return 'delete' // 默认操作名 return `${method.toLowerCase()}_${path.replace(/[^a-zA-Z0-9]/g, '_')}` }, // 提取basePath extractBasePath(paths) { if (paths.length === 0) return '' // 找到所有路径的共同前缀 const firstPath = paths[0] let commonPrefix = '' for (let i = 0; i < firstPath.length; i++) { const char = firstPath[i] if (paths.every(path => path[i] === char)) { commonPrefix += char } else { break } } // 如果找到了完整的前缀,返回它 if (commonPrefix && !commonPrefix.endsWith('/')) { // 找到最后一个斜杠的位置 const lastSlashIndex = commonPrefix.lastIndexOf('/') if (lastSlashIndex > 0) { return commonPrefix.substring(0, lastSlashIndex + 1) } } return commonPrefix }, // 获取默认API映射(当无法从服务文件提取时) getDefaultApiMapping(moduleName) { const defaults = { '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' } } }, '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' } } } } return defaults[moduleName] || { basePath: `/api/${moduleName}`, operations: { list: { path: '', method: 'GET' } } } }, // 解析路由配置 parseRoutes(content) { // 简单的路由解析逻辑 const routes = [] const routeRegex = /path:\s*['"`]([^'"`]+)['"`]/g const nameRegex = /name:\s*['"`]([^'"`]+)['"`]/g let match while ((match = routeRegex.exec(content)) !== null) { const path = match[1] const nameMatch = nameRegex.exec(content) const name = nameMatch ? nameMatch[1] : path.split('/').pop() routes.push({ path, name, module: this.extractModuleFromPath(path) }) } return routes }, // 从路径提取模块名 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-test': 'route-sync' } return moduleMap[module] || module }, // 生成主入口路由 generateMainRoutes(routes) { const mainRoutes = [] const processedModules = new Set() routes.forEach(route => { const module = route.module // 只处理主入口路由,避免重复 if (!processedModules.has(module)) { mainRoutes.push({ path: route.path, name: route.name, module: module, description: this.generateDescription(route.name, module), type: this.determineRouteType(route.path, module) }) processedModules.add(module) } }) return mainRoutes }, // 生成路由描述 generateDescription(name, module) { const descriptions = { 'home': '首页', 'user-management': '用户管理', 'role-management': '角色管理', 'system-settings': '系统设置', 'route-sync': '路由同步测试' } return descriptions[module] || `${name}页面` }, // 确定路由类型 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' }, // 生成路由映射文件 generateRouteMappingFile(mainRoutes, moduleApiMappings) { const mappingContent = `// 自动生成的路由映射文件 // 此文件由 route-mapping-plugin 在构建时生成 // 请勿手动修改 export const mainRoutes = ${JSON.stringify(mainRoutes, null, 2)} // 模块到API映射配置(从实际服务文件中提取) export const moduleApiMappings = ${JSON.stringify(moduleApiMappings, null, 2)} // 子路由到主路由的映射 export const subRouteMappings = { '/user-management/create': { mainRoute: '/user-management', operation: 'create' }, '/user-management/edit': { mainRoute: '/user-management', operation: 'update' }, '/user-management/delete': { mainRoute: '/user-management', operation: 'delete' }, '/user-management/detail': { mainRoute: '/user-management', operation: 'detail' }, '/role-management/create': { mainRoute: '/role-management', operation: 'create' }, '/role-management/edit': { mainRoute: '/role-management', operation: 'update' }, '/role-management/delete': { mainRoute: '/role-management', operation: 'delete' }, '/role-management/detail': { mainRoute: '/role-management', operation: 'detail' } } export default { mainRoutes, moduleApiMappings, subRouteMappings } ` const outputPath = resolve(__dirname, '../src/renderer/modules/route-sync/generated-route-mapping.js') fs.writeFileSync(outputPath, mappingContent, 'utf-8') console.log(`✅ 路由映射文件已生成: ${outputPath}`) } } }