front/scripts/import-api-menus-browser.js
2026-01-24 11:55:01 +08:00

223 lines
6.2 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* API 菜单批量导入脚本(浏览器版本)
* 在浏览器控制台中运行此脚本
*
* 使用方法:
* 1. 打开浏览器控制台(F12)
* 2. 确保已登录系统
* 3. 复制并运行以下代码
*/
// 菜单标题映射
const menuTitleMap = {
'menu.api': 'API',
'menu.api.upstreamInterface': '上游接口',
'menu.api.downstreamInterface': '下游接口',
'menu.api.appList': 'App列表',
'menu.api.requestLog': '请求日志',
'menu.api.callStatistics': '调用统计',
'menu.api.apiDebugger': 'API调试',
};
// API 路由配置
const apiRoutes = {
parent: {
name: 'API',
path: '/api',
icon: 'icon-computer',
order: 1,
},
children: [
{
path: 'upstreamInterface',
name: 'UpstreamInterface',
component: 'views/api/upstreamInterface/index',
locale: 'menu.api.upstreamInterface',
permission: 'Api.Interfaces.Query',
icon: 'icon-code',
order: 1,
},
{
path: 'downstreamInterface',
name: 'DownstreamInterface',
component: 'views/api/downstreamInterface/index',
locale: 'menu.api.downstreamInterface',
permission: 'Api.ServiceProviders.Query',
icon: 'icon-code',
order: 2,
},
{
path: 'appList',
name: 'AppList',
component: 'views/api/appList/index',
locale: 'menu.api.appList',
permission: 'Api.Applications.Query',
icon: 'icon-apps',
order: 3,
},
{
path: 'requestLog',
name: 'RequestLog',
component: 'views/api/requestLog/index',
locale: 'menu.api.requestLog',
permission: 'Api.Logs.Query',
icon: 'icon-file-text',
order: 4,
},
{
path: 'callStatistics',
name: 'CallStatistics',
component: 'views/api/callStatistics/index',
locale: 'menu.api.callStatistics',
permission: 'Api.Statistics.Query',
icon: 'icon-bar-chart',
order: 5,
},
{
path: 'apiDebugger',
name: 'ApiDebugger',
component: 'views/api/apiDebugger/index',
locale: 'menu.api.apiDebugger',
permission: 'Api.Debugger.Query',
icon: 'icon-bug',
order: 6,
},
],
};
/**
* 批量导入 API 菜单
*/
async function importApiMenus() {
try {
console.log('🚀 开始导入 API 菜单...');
// 动态导入 MenuService(需要根据实际路径调整)
const { MenuService } = await import('/src/api/rbac/generated/services/MenuService.js');
// 1. 获取已有菜单
let existingMenus = [];
try {
existingMenus = await MenuService.getRbacMenuGetMenuTree();
console.log('📋 获取到已有菜单数量:', existingMenus.length);
} catch (error) {
console.warn('⚠️ 获取已有菜单失败,将继续导入:', error);
}
// 收集已有菜单的 route
const existingRoutes = new Set();
function collectRoutes(menus) {
menus.forEach(menu => {
if (menu.route) {
existingRoutes.add(menu.route);
}
if (menu.children && menu.children.length > 0) {
collectRoutes(menu.children);
}
});
}
collectRoutes(existingMenus);
// 2. 创建父菜单(API 主菜单)
let apiParentId = null;
const existingParent = existingMenus.find(m => m.route === '/api');
if (existingParent) {
apiParentId = existingParent.id;
console.log('✅ API 主菜单已存在,ID:', apiParentId);
} else {
const parentMenu = {
pId: null,
name: apiRoutes.parent.name,
type: 1,
permissionCode: null,
icon: apiRoutes.parent.icon,
route: apiRoutes.parent.path,
component: null,
order: apiRoutes.parent.order,
isHidden: false,
isCached: false,
description: 'API 管理模块',
};
try {
const result = await MenuService.postRbacMenuCreate(parentMenu);
apiParentId = result.id;
console.log('✅ 成功创建 API 主菜单,ID:', apiParentId);
} catch (error) {
console.error('❌ 创建 API 主菜单失败:', error);
throw error;
}
}
// 3. 创建子菜单
let successCount = 0;
let skipCount = 0;
let failCount = 0;
for (const route of apiRoutes.children) {
const routePath = `/api/${route.path}`;
// 检查是否已存在
if (existingRoutes.has(routePath)) {
skipCount++;
console.log(`⏭️ 菜单已存在,跳过: ${menuTitleMap[route.locale] || route.name} (${routePath})`);
continue;
}
const menuData = {
pId: apiParentId,
name: menuTitleMap[route.locale] || route.name,
type: 1,
permissionCode: route.permission,
icon: route.icon,
route: routePath,
component: route.component,
order: route.order,
isHidden: false,
isCached: false,
description: `从路由配置导入: ${routePath}`,
};
try {
await MenuService.postRbacMenuCreate(menuData);
successCount++;
console.log(`✅ 成功导入: ${menuData.name} (${routePath})`);
} catch (error) {
if (error.status === 400 || error.status === 409) {
skipCount++;
console.log(`⏭️ 菜单已存在,跳过: ${menuData.name} (${routePath})`);
} else {
failCount++;
console.error(`❌ 导入失败: ${menuData.name} (${routePath})`, error);
}
}
}
console.log('\n📊 === 导入完成 ===');
console.log(`✅ 成功: ${successCount} 个`);
console.log(`⏭️ 跳过: ${skipCount} 个`);
console.log(`❌ 失败: ${failCount} 个`);
console.log(`📦 总计: ${apiRoutes.children.length} 个`);
return {
success: successCount,
skip: skipCount,
fail: failCount,
total: apiRoutes.children.length,
};
} catch (error) {
console.error('❌ 批量导入菜单失败:', error);
throw error;
}
}
// 导出到全局
if (typeof window !== 'undefined') {
window.importApiMenus = importApiMenus;
console.log('📝 API 菜单导入函数已挂载到 window.importApiMenus');
console.log('💡 使用方法: await window.importApiMenus()');
}
export { importApiMenus };