|
|
|
|
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}`)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|