// eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-nocheck // 加载环境变量(必须在其他导入之前) import * as dotenv from 'dotenv'; import * as path from 'path'; // 根据 NODE_ENV 加载对应的环境配置文件 const nodeEnv = process.env.NODE_ENV || 'development'; const envFile = `.env.${nodeEnv}`; // scripts 目录的父目录就是 backend 目录 const backendDir = path.resolve(__dirname, '..'); const envPath = path.resolve(backendDir, envFile); // 尝试加载环境特定的配置文件 dotenv.config({ path: envPath }); // 如果环境特定文件不存在,尝试加载默认的 .env 文件 if (!process.env.DATABASE_URL) { dotenv.config({ path: path.resolve(backendDir, '.env') }); } // 验证必要的环境变量 if (!process.env.DATABASE_URL) { console.error('❌ 错误: 未找到 DATABASE_URL 环境变量'); console.error(` 请确保存在以下文件之一:`); console.error(` - ${envPath}`); console.error(` - ${path.resolve(backendDir, '.env')}`); console.error(` 或者设置 NODE_ENV 环境变量(当前: ${nodeEnv})`); process.exit(1); } import { PrismaClient } from '@prisma/client'; import * as fs from 'fs'; const prisma = new PrismaClient(); // 从 JSON 文件加载菜单数据 const menusFilePath = path.resolve(backendDir, 'data', 'menus.json'); if (!fs.existsSync(menusFilePath)) { console.error(`❌ 错误: 菜单数据文件不存在: ${menusFilePath}`); process.exit(1); } const menus = JSON.parse(fs.readFileSync(menusFilePath, 'utf-8')); async function initMenus() { try { console.log('🚀 开始初始化菜单数据...\n'); // 递归创建菜单 async function createMenu(menuData: any, parentId: number | null = null) { const { children, ...menuFields } = menuData; // 查找是否已存在相同名称和父菜单的菜单 const existingMenu = await prisma.menu.findFirst({ where: { name: menuFields.name, parentId: parentId, }, }); let menu; if (existingMenu) { // 更新现有菜单 menu = await prisma.menu.update({ where: { id: existingMenu.id }, data: { name: menuFields.name, path: menuFields.path || null, icon: menuFields.icon || null, component: menuFields.component || null, permission: menuFields.permission || null, parentId: parentId, sort: menuFields.sort || 0, validState: 1, }, }); } else { // 创建新菜单 menu = await prisma.menu.create({ data: { name: menuFields.name, path: menuFields.path || null, icon: menuFields.icon || null, component: menuFields.component || null, permission: menuFields.permission || null, parentId: parentId, sort: menuFields.sort || 0, validState: 1, }, }); } console.log(` ✓ ${menu.name} (${menu.path || '无路径'})`); // 如果有子菜单,递归创建 if (children && children.length > 0) { for (const child of children) { await createMenu(child, menu.id); } } return menu; } // 清空现有菜单(重新初始化) console.log('🗑️ 清空现有菜单...'); // 先删除所有子菜单,再删除父菜单(避免外键约束问题) await prisma.menu.deleteMany({ where: { parentId: { not: null, }, }, }); await prisma.menu.deleteMany({ where: { parentId: null, }, }); console.log('✅ 已清空现有菜单\n'); // 创建所有菜单 console.log('📝 创建菜单...\n'); for (const menu of menus) { await createMenu(menu); } // 验证结果 console.log('\n🔍 验证结果...'); const allMenus = await prisma.menu.findMany({ orderBy: [{ sort: 'asc' }, { id: 'asc' }], include: { children: { orderBy: { sort: 'asc', }, }, }, }); const topLevelMenus = allMenus.filter((m) => !m.parentId); const totalMenus = allMenus.length; console.log(`\n📊 初始化结果:`); console.log(` 顶级菜单数量: ${topLevelMenus.length}`); console.log(` 总菜单数量: ${totalMenus}`); console.log(`\n📋 菜单结构:`); function printMenuTree(menu: any, indent: string = '') { console.log(`${indent}├─ ${menu.name} (${menu.path || '无路径'})`); if (menu.children && menu.children.length > 0) { menu.children.forEach((child: any, index: number) => { const isLast = index === menu.children.length - 1; const childIndent = indent + (isLast ? ' ' : '│ '); printMenuTree(child, childIndent); }); } } topLevelMenus.forEach((menu) => { printMenuTree(menu); }); // 为所有现有租户分配新菜单 console.log(`\n📋 为所有租户分配菜单...`); const allTenants = await prisma.tenant.findMany({ where: { validState: 1 }, }); if (allTenants.length === 0) { console.log('⚠️ 没有找到任何有效租户,跳过菜单分配\n'); } else { console.log(` 找到 ${allTenants.length} 个租户\n`); for (const tenant of allTenants) { // 获取租户已分配的菜单 const existingTenantMenus = await prisma.tenantMenu.findMany({ where: { tenantId: tenant.id }, select: { menuId: true }, }); const existingMenuIds = new Set( existingTenantMenus.map((tm) => tm.menuId), ); // 为租户分配所有新菜单 let addedMenuCount = 0; for (const menu of allMenus) { if (!existingMenuIds.has(menu.id)) { await prisma.tenantMenu.create({ data: { tenantId: tenant.id, menuId: menu.id, }, }); addedMenuCount++; } } if (addedMenuCount > 0) { console.log( ` ✓ 租户 "${tenant.name}" (${tenant.code}): 添加了 ${addedMenuCount} 个菜单`, ); } else { console.log( ` ✓ 租户 "${tenant.name}" (${tenant.code}): 已拥有所有菜单`, ); } } console.log(`\n✅ 菜单分配完成!`); } console.log(`\n✅ 菜单初始化完成!`); } catch (error) { console.error('\n💥 初始化菜单失败:', error); throw error; } finally { await prisma.$disconnect(); } } // 执行初始化 initMenus() .then(() => { console.log('\n🎉 菜单初始化脚本执行完成!'); process.exit(0); }) .catch((error) => { console.error('\n💥 菜单初始化脚本执行失败:', error); process.exit(1); });