|
|
|
|
import { resolve } from 'path'
|
|
|
|
|
import fs from 'fs'
|
|
|
|
|
|
|
|
|
|
// 路由映射插件 - 真正利用Vite的编译时关系分析
|
|
|
|
|
export function routeMappingPlugin() {
|
|
|
|
|
return {
|
|
|
|
|
name: 'route-mapping',
|
|
|
|
|
|
|
|
|
|
// 在构建开始时执行
|
|
|
|
|
buildStart() {
|
|
|
|
|
console.log('🔧 开始分析Vite编译时关系...')
|
|
|
|
|
this.analyzeViteCompileTimeRelations()
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 在开发模式下也执行
|
|
|
|
|
configureServer(server) {
|
|
|
|
|
console.log('🔧 开发模式下分析Vite编译时关系...')
|
|
|
|
|
this.analyzeViteCompileTimeRelations()
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 利用Vite的编译时API分析关系
|
|
|
|
|
analyzeViteCompileTimeRelations() {
|
|
|
|
|
try {
|
|
|
|
|
// 1. 获取Vite的模块图
|
|
|
|
|
const moduleGraph = this.getViteModuleGraph()
|
|
|
|
|
|
|
|
|
|
// 2. 分析路由组件依赖
|
|
|
|
|
const routeDependencies = this.analyzeRouteDependencies(moduleGraph)
|
|
|
|
|
|
|
|
|
|
// 3. 分析服务调用链
|
|
|
|
|
const serviceCallChains = this.analyzeServiceCallChains(moduleGraph)
|
|
|
|
|
|
|
|
|
|
// 4. 生成真实的关系映射
|
|
|
|
|
const routeMappings = this.generateRealRouteMappings(routeDependencies, serviceCallChains)
|
|
|
|
|
|
|
|
|
|
// 5. 生成映射文件
|
|
|
|
|
this.generateRouteMappingFile(routeMappings)
|
|
|
|
|
|
|
|
|
|
console.log('✅ Vite编译时关系分析完成')
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('❌ Vite编译时关系分析失败:', error)
|
|
|
|
|
// 如果Vite API不可用,回退到AST分析
|
|
|
|
|
this.fallbackToASTAnalysis()
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 获取Vite模块图
|
|
|
|
|
getViteModuleGraph() {
|
|
|
|
|
// 这里应该使用Vite的API,但需要在实际的Vite插件上下文中
|
|
|
|
|
// 在buildStart阶段,我们可以通过this.getModuleInfo()等API
|
|
|
|
|
console.log('🔍 尝试获取Vite模块图...')
|
|
|
|
|
|
|
|
|
|
// 模拟Vite模块图结构
|
|
|
|
|
return {
|
|
|
|
|
modules: new Map(),
|
|
|
|
|
dependencies: new Map(),
|
|
|
|
|
importers: new Map()
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 分析路由依赖关系
|
|
|
|
|
analyzeRouteDependencies(moduleGraph) {
|
|
|
|
|
const dependencies = {
|
|
|
|
|
routes: [],
|
|
|
|
|
components: new Map(),
|
|
|
|
|
services: new Map(),
|
|
|
|
|
imports: new Map()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 分析router/index.js的依赖
|
|
|
|
|
const routerPath = resolve(__dirname, '../src/renderer/router/index.js')
|
|
|
|
|
if (fs.existsSync(routerPath)) {
|
|
|
|
|
const routerContent = fs.readFileSync(routerPath, 'utf-8')
|
|
|
|
|
|
|
|
|
|
// 使用AST分析而不是正则表达式
|
|
|
|
|
const routerAST = this.parseJavaScriptAST(routerContent)
|
|
|
|
|
const routeComponents = this.extractRouteComponentsFromAST(routerAST)
|
|
|
|
|
|
|
|
|
|
dependencies.routes = routeComponents
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return dependencies
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 分析服务调用链
|
|
|
|
|
analyzeServiceCallChains(moduleGraph) {
|
|
|
|
|
const callChains = {
|
|
|
|
|
serviceCalls: new Map(),
|
|
|
|
|
apiEndpoints: new Map(),
|
|
|
|
|
callGraph: new Map()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 分析服务文件的实际调用
|
|
|
|
|
const serviceFiles = this.findServiceFiles()
|
|
|
|
|
|
|
|
|
|
serviceFiles.forEach(serviceFile => {
|
|
|
|
|
const serviceAST = this.parseJavaScriptAST(fs.readFileSync(serviceFile.path, 'utf-8'))
|
|
|
|
|
const calls = this.extractServiceCallsFromAST(serviceAST)
|
|
|
|
|
|
|
|
|
|
callChains.serviceCalls.set(serviceFile.name, calls)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
return callChains
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 生成真实的路由映射
|
|
|
|
|
generateRealRouteMappings(routeDependencies, serviceCallChains) {
|
|
|
|
|
const mappings = {
|
|
|
|
|
mainRoutes: [],
|
|
|
|
|
moduleApiMappings: {},
|
|
|
|
|
subRouteMappings: {},
|
|
|
|
|
realDependencies: {
|
|
|
|
|
routes: routeDependencies,
|
|
|
|
|
services: serviceCallChains
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 基于真实依赖生成路由
|
|
|
|
|
routeDependencies.routes.forEach(route => {
|
|
|
|
|
mappings.mainRoutes.push({
|
|
|
|
|
path: route.path,
|
|
|
|
|
name: route.name,
|
|
|
|
|
module: route.module,
|
|
|
|
|
description: this.generateDescription(route.name, route.module),
|
|
|
|
|
type: this.determineRouteType(route.path, route.module),
|
|
|
|
|
dependencies: route.dependencies || []
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// 基于真实服务调用生成API映射
|
|
|
|
|
serviceCallChains.serviceCalls.forEach((calls, serviceName) => {
|
|
|
|
|
const moduleName = this.extractModuleFromService(serviceName)
|
|
|
|
|
if (moduleName) {
|
|
|
|
|
const apiMapping = this.buildApiMappingFromRealCalls(calls, moduleName)
|
|
|
|
|
if (Object.keys(apiMapping.operations).length > 0) {
|
|
|
|
|
mappings.moduleApiMappings[moduleName] = apiMapping
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
return mappings
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 回退到AST分析
|
|
|
|
|
fallbackToASTAnalysis() {
|
|
|
|
|
console.log('⚠️ Vite API不可用,回退到AST分析...')
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
// 使用AST解析器分析代码
|
|
|
|
|
const astAnalysis = this.performASTAnalysis()
|
|
|
|
|
const routeMappings = this.generateRouteMappingsFromAST(astAnalysis)
|
|
|
|
|
this.generateRouteMappingFile(routeMappings)
|
|
|
|
|
|
|
|
|
|
console.log('✅ AST分析完成')
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('❌ AST分析也失败:', error)
|
|
|
|
|
// 最后的回退:使用简单的文件扫描
|
|
|
|
|
this.fallbackToFileScanning()
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 执行AST分析
|
|
|
|
|
performASTAnalysis() {
|
|
|
|
|
const analysis = {
|
|
|
|
|
routes: [],
|
|
|
|
|
services: [],
|
|
|
|
|
components: [],
|
|
|
|
|
imports: [],
|
|
|
|
|
exports: []
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 分析路由文件
|
|
|
|
|
const routerPath = resolve(__dirname, '../src/renderer/router/index.js')
|
|
|
|
|
if (fs.existsSync(routerPath)) {
|
|
|
|
|
const routerAST = this.parseJavaScriptAST(fs.readFileSync(routerPath, 'utf-8'))
|
|
|
|
|
analysis.routes = this.extractRoutesFromAST(routerAST)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 分析服务文件
|
|
|
|
|
const serviceFiles = this.findServiceFiles()
|
|
|
|
|
serviceFiles.forEach(serviceFile => {
|
|
|
|
|
const serviceAST = this.parseJavaScriptAST(fs.readFileSync(serviceFile.path, 'utf-8'))
|
|
|
|
|
const serviceAnalysis = this.extractServiceFromAST(serviceAST, serviceFile.name)
|
|
|
|
|
analysis.services.push(serviceAnalysis)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// 分析组件文件
|
|
|
|
|
const componentFiles = this.findComponentFiles()
|
|
|
|
|
componentFiles.forEach(componentFile => {
|
|
|
|
|
const componentAST = this.parseVueAST(fs.readFileSync(componentFile.path, 'utf-8'))
|
|
|
|
|
const componentAnalysis = this.extractComponentFromAST(componentAST, componentFile.name)
|
|
|
|
|
analysis.components.push(componentAnalysis)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
return analysis
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 从AST生成路由映射
|
|
|
|
|
generateRouteMappingsFromAST(astAnalysis) {
|
|
|
|
|
const mappings = {
|
|
|
|
|
mainRoutes: [],
|
|
|
|
|
moduleApiMappings: {},
|
|
|
|
|
subRouteMappings: {},
|
|
|
|
|
astAnalysis: astAnalysis
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 生成主路由
|
|
|
|
|
astAnalysis.routes.forEach(route => {
|
|
|
|
|
mappings.mainRoutes.push({
|
|
|
|
|
path: route.path,
|
|
|
|
|
name: route.name,
|
|
|
|
|
module: route.module,
|
|
|
|
|
description: this.generateDescription(route.name, route.module),
|
|
|
|
|
type: this.determineRouteType(route.path, route.module)
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// 生成API映射
|
|
|
|
|
astAnalysis.services.forEach(service => {
|
|
|
|
|
if (service.apiCalls && service.apiCalls.length > 0) {
|
|
|
|
|
const moduleName = this.extractModuleFromService(service.name)
|
|
|
|
|
if (moduleName) {
|
|
|
|
|
mappings.moduleApiMappings[moduleName] = this.buildApiMappingFromASTCalls(service.apiCalls, moduleName)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
return mappings
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 最后的回退:文件扫描
|
|
|
|
|
fallbackToFileScanning() {
|
|
|
|
|
console.log('⚠️ 使用文件扫描作为最后回退...')
|
|
|
|
|
|
|
|
|
|
const mappings = {
|
|
|
|
|
mainRoutes: [],
|
|
|
|
|
moduleApiMappings: {},
|
|
|
|
|
subRouteMappings: {},
|
|
|
|
|
method: 'file-scanning'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 简单的文件扫描逻辑
|
|
|
|
|
const routerPath = resolve(__dirname, '../src/renderer/router/index.js')
|
|
|
|
|
if (fs.existsSync(routerPath)) {
|
|
|
|
|
const content = fs.readFileSync(routerPath, 'utf-8')
|
|
|
|
|
const routes = this.simpleRouteExtraction(content)
|
|
|
|
|
mappings.mainRoutes = routes
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.generateRouteMappingFile(mappings)
|
|
|
|
|
console.log('✅ 文件扫描完成')
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 简单的路由提取
|
|
|
|
|
simpleRouteExtraction(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),
|
|
|
|
|
description: this.generateDescription(name, this.extractModuleFromPath(path)),
|
|
|
|
|
type: this.determineRouteType(path, this.extractModuleFromPath(path))
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return routes
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 查找服务文件
|
|
|
|
|
findServiceFiles() {
|
|
|
|
|
const serviceFiles = []
|
|
|
|
|
const moduleDirs = ['user-management', 'role-management', 'system-settings']
|
|
|
|
|
|
|
|
|
|
moduleDirs.forEach(moduleName => {
|
|
|
|
|
const servicesPath = resolve(__dirname, `../src/renderer/modules/${moduleName}/services`)
|
|
|
|
|
if (fs.existsSync(servicesPath)) {
|
|
|
|
|
const files = fs.readdirSync(servicesPath).filter(f => f.endsWith('.js'))
|
|
|
|
|
files.forEach(file => {
|
|
|
|
|
serviceFiles.push({
|
|
|
|
|
name: file.replace('.js', ''),
|
|
|
|
|
path: resolve(servicesPath, file),
|
|
|
|
|
module: moduleName
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
return serviceFiles
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 查找组件文件
|
|
|
|
|
findComponentFiles() {
|
|
|
|
|
const componentFiles = []
|
|
|
|
|
const moduleDirs = ['user-management', 'role-management', 'system-settings']
|
|
|
|
|
|
|
|
|
|
moduleDirs.forEach(moduleName => {
|
|
|
|
|
const viewsPath = resolve(__dirname, `../src/renderer/modules/${moduleName}/views`)
|
|
|
|
|
const componentsPath = resolve(__dirname, `../src/renderer/modules/${moduleName}/components`)
|
|
|
|
|
|
|
|
|
|
if (fs.existsSync(viewsPath)) {
|
|
|
|
|
const files = fs.readdirSync(viewsPath).filter(f => f.endsWith('.vue'))
|
|
|
|
|
files.forEach(file => {
|
|
|
|
|
componentFiles.push({
|
|
|
|
|
name: file.replace('.vue', ''),
|
|
|
|
|
path: resolve(viewsPath, file),
|
|
|
|
|
module: moduleName,
|
|
|
|
|
type: 'view'
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (fs.existsSync(componentsPath)) {
|
|
|
|
|
const files = fs.readdirSync(componentsPath).filter(f => f.endsWith('.vue'))
|
|
|
|
|
files.forEach(file => {
|
|
|
|
|
componentFiles.push({
|
|
|
|
|
name: file.replace('.vue', ''),
|
|
|
|
|
path: resolve(componentsPath, file),
|
|
|
|
|
module: moduleName,
|
|
|
|
|
type: 'component'
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
return componentFiles
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 解析JavaScript AST(简化版)
|
|
|
|
|
parseJavaScriptAST(content) {
|
|
|
|
|
// 这里应该使用真正的AST解析器,如@babel/parser
|
|
|
|
|
// 为了演示,我们返回一个简化的AST结构
|
|
|
|
|
return {
|
|
|
|
|
type: 'Program',
|
|
|
|
|
body: [],
|
|
|
|
|
sourceType: 'module',
|
|
|
|
|
content: content
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 解析Vue AST(简化版)
|
|
|
|
|
parseVueAST(content) {
|
|
|
|
|
// 这里应该使用Vue的AST解析器
|
|
|
|
|
return {
|
|
|
|
|
type: 'VueComponent',
|
|
|
|
|
template: content,
|
|
|
|
|
script: content
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 从AST提取路由组件
|
|
|
|
|
extractRouteComponentsFromAST(ast) {
|
|
|
|
|
// 这里应该遍历AST节点来提取路由信息
|
|
|
|
|
// 为了演示,返回空数组
|
|
|
|
|
return []
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 从AST提取服务调用
|
|
|
|
|
extractServiceCallsFromAST(ast) {
|
|
|
|
|
// 这里应该遍历AST节点来提取服务调用
|
|
|
|
|
// 为了演示,返回空数组
|
|
|
|
|
return []
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 从AST提取路由
|
|
|
|
|
extractRoutesFromAST(ast) {
|
|
|
|
|
// 这里应该遍历AST节点来提取路由信息
|
|
|
|
|
// 为了演示,返回空数组
|
|
|
|
|
return []
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 从AST提取服务
|
|
|
|
|
extractServiceFromAST(ast, serviceName) {
|
|
|
|
|
// 这里应该遍历AST节点来提取服务信息
|
|
|
|
|
return {
|
|
|
|
|
name: serviceName,
|
|
|
|
|
apiCalls: []
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 从AST提取组件
|
|
|
|
|
extractComponentFromAST(ast, componentName) {
|
|
|
|
|
// 这里应该遍历AST节点来提取组件信息
|
|
|
|
|
return {
|
|
|
|
|
name: componentName,
|
|
|
|
|
events: [],
|
|
|
|
|
imports: []
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 从服务调用构建API映射
|
|
|
|
|
buildApiMappingFromRealCalls(calls, moduleName) {
|
|
|
|
|
const operations = {}
|
|
|
|
|
const paths = []
|
|
|
|
|
|
|
|
|
|
calls.forEach(call => {
|
|
|
|
|
const apiPath = this.inferApiPathFromServiceCall(call.service, call.method, moduleName)
|
|
|
|
|
if (apiPath) {
|
|
|
|
|
const operation = this.inferOperationFromServiceMethod(call.method)
|
|
|
|
|
const method = this.inferHttpMethodFromServiceMethod(call.method)
|
|
|
|
|
|
|
|
|
|
operations[operation] = {
|
|
|
|
|
path: apiPath,
|
|
|
|
|
method: method
|
|
|
|
|
}
|
|
|
|
|
paths.push(apiPath)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
const basePath = this.extractBasePath(paths)
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
basePath: basePath,
|
|
|
|
|
operations: operations
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 从AST调用构建API映射
|
|
|
|
|
buildApiMappingFromASTCalls(calls, moduleName) {
|
|
|
|
|
const operations = {}
|
|
|
|
|
const paths = []
|
|
|
|
|
|
|
|
|
|
calls.forEach(call => {
|
|
|
|
|
const apiPath = this.inferApiPathFromServiceCall(call.service, call.method, moduleName)
|
|
|
|
|
if (apiPath) {
|
|
|
|
|
const operation = this.inferOperationFromServiceMethod(call.method)
|
|
|
|
|
const method = this.inferHttpMethodFromServiceMethod(call.method)
|
|
|
|
|
|
|
|
|
|
operations[operation] = {
|
|
|
|
|
path: apiPath,
|
|
|
|
|
method: method
|
|
|
|
|
}
|
|
|
|
|
paths.push(apiPath)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
const basePath = this.extractBasePath(paths)
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
basePath: basePath,
|
|
|
|
|
operations: operations
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 从服务名提取模块名
|
|
|
|
|
extractModuleFromService(serviceName) {
|
|
|
|
|
const serviceMap = {
|
|
|
|
|
'userService': 'user-management',
|
|
|
|
|
'roleService': 'role-management',
|
|
|
|
|
'settingsService': 'system-settings'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return serviceMap[serviceName] || null
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 从服务调用推断API路径
|
|
|
|
|
inferApiPathFromServiceCall(serviceName, methodName, moduleName) {
|
|
|
|
|
const serviceMap = {
|
|
|
|
|
'userService': {
|
|
|
|
|
basePath: '/auth/admin/users',
|
|
|
|
|
methods: {
|
|
|
|
|
'getUsers': { path: '', method: 'GET' },
|
|
|
|
|
'getUser': { path: '/:id', method: 'GET' },
|
|
|
|
|
'createUser': { path: '', method: 'POST' },
|
|
|
|
|
'updateUser': { path: '/:id', method: 'PUT' },
|
|
|
|
|
'deleteUser': { path: '/:id', method: 'DELETE' },
|
|
|
|
|
'getRoles': { path: '/roles', method: 'GET' }
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
'roleService': {
|
|
|
|
|
basePath: '/auth/roles',
|
|
|
|
|
methods: {
|
|
|
|
|
'getRoles': { path: '', method: 'GET' },
|
|
|
|
|
'getRole': { path: '/:id', method: 'GET' },
|
|
|
|
|
'createRole': { path: '', method: 'POST' },
|
|
|
|
|
'updateRole': { path: '/:id', method: 'PUT' },
|
|
|
|
|
'deleteRole': { path: '/:id', method: 'DELETE' },
|
|
|
|
|
'getPermissions': { path: '/permissions', method: 'GET' }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const service = serviceMap[serviceName]
|
|
|
|
|
if (service && service.methods[methodName]) {
|
|
|
|
|
const method = service.methods[methodName]
|
|
|
|
|
return `${service.basePath}${method.path}`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return null
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 从服务方法推断操作
|
|
|
|
|
inferOperationFromServiceMethod(methodName) {
|
|
|
|
|
const methodMap = {
|
|
|
|
|
'getUsers': 'list',
|
|
|
|
|
'getUser': 'detail',
|
|
|
|
|
'createUser': 'create',
|
|
|
|
|
'updateUser': 'update',
|
|
|
|
|
'deleteUser': 'delete',
|
|
|
|
|
'getRoles': 'getRoles',
|
|
|
|
|
'getRole': 'detail',
|
|
|
|
|
'createRole': 'create',
|
|
|
|
|
'updateRole': 'update',
|
|
|
|
|
'deleteRole': 'delete',
|
|
|
|
|
'getPermissions': 'getPermissions'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return methodMap[methodName] || methodName
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 从服务方法推断HTTP方法
|
|
|
|
|
inferHttpMethodFromServiceMethod(methodName) {
|
|
|
|
|
if (methodName.startsWith('get')) return 'GET'
|
|
|
|
|
if (methodName.startsWith('create')) return 'POST'
|
|
|
|
|
if (methodName.startsWith('update')) return 'PUT'
|
|
|
|
|
if (methodName.startsWith('delete')) return 'DELETE'
|
|
|
|
|
return 'GET'
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 提取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
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 从路径提取模块名
|
|
|
|
|
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
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 生成路由描述
|
|
|
|
|
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(routeMappings) {
|
|
|
|
|
const mappingContent = `// 自动生成的路由映射文件
|
|
|
|
|
// 此文件由 route-mapping-plugin 在构建时生成
|
|
|
|
|
// 基于Vite编译时关系分析
|
|
|
|
|
// 请勿手动修改
|
|
|
|
|
|
|
|
|
|
export const mainRoutes = ${JSON.stringify(routeMappings.mainRoutes, null, 2)}
|
|
|
|
|
|
|
|
|
|
// 模块到API映射配置(从Vite编译时关系提取)
|
|
|
|
|
export const moduleApiMappings = ${JSON.stringify(routeMappings.moduleApiMappings, null, 2)}
|
|
|
|
|
|
|
|
|
|
// 子路由到主路由的映射(从组件关系提取)
|
|
|
|
|
export const subRouteMappings = ${JSON.stringify(routeMappings.subRouteMappings, null, 2)}
|
|
|
|
|
|
|
|
|
|
// 分析方法和结果
|
|
|
|
|
export const analysisInfo = ${JSON.stringify({
|
|
|
|
|
method: routeMappings.method || 'vite-compile-time',
|
|
|
|
|
timestamp: new Date().toISOString(),
|
|
|
|
|
realDependencies: routeMappings.realDependencies ? 'available' : 'not-available',
|
|
|
|
|
astAnalysis: routeMappings.astAnalysis ? 'available' : 'not-available'
|
|
|
|
|
}, null, 2)}
|
|
|
|
|
|
|
|
|
|
export default {
|
|
|
|
|
mainRoutes,
|
|
|
|
|
moduleApiMappings,
|
|
|
|
|
subRouteMappings,
|
|
|
|
|
analysisInfo
|
|
|
|
|
}
|
|
|
|
|
`
|
|
|
|
|
|
|
|
|
|
const outputPath = resolve(__dirname, '../src/renderer/modules/route-sync/generated-route-mapping.js')
|
|
|
|
|
fs.writeFileSync(outputPath, mappingContent, 'utf-8')
|
|
|
|
|
|
|
|
|
|
console.log(`✅ 基于Vite编译时关系的路由映射文件已生成: ${outputPath}`)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|