// 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}`; const backendDir = path.resolve(__dirname, '..'); const envPath = path.resolve(backendDir, envFile); dotenv.config({ path: envPath }); if (!process.env.DATABASE_URL) { dotenv.config({ path: path.resolve(backendDir, '.env') }); } if (!process.env.DATABASE_URL) { console.error('❌ 错误: 未找到 DATABASE_URL 环境变量'); process.exit(1); } import { PrismaClient } from '@prisma/client'; import * as bcrypt from 'bcrypt'; const prisma = new PrismaClient(); // 超级管理员基础权限 const permissions = [ // 工作台 { code: 'workbench:read', resource: 'workbench', action: 'read', name: '查看工作台', description: '允许查看工作台' }, // 用户管理 { code: 'user:create', resource: 'user', action: 'create', name: '创建用户', description: '允许创建新用户' }, { code: 'user:read', resource: 'user', action: 'read', name: '查看用户', description: '允许查看用户列表和详情' }, { code: 'user:update', resource: 'user', action: 'update', name: '更新用户', description: '允许更新用户信息' }, { code: 'user:delete', resource: 'user', action: 'delete', name: '删除用户', description: '允许删除用户' }, // 角色管理 { code: 'role:create', resource: 'role', action: 'create', name: '创建角色', description: '允许创建新角色' }, { code: 'role:read', resource: 'role', action: 'read', name: '查看角色', description: '允许查看角色列表和详情' }, { code: 'role:update', resource: 'role', action: 'update', name: '更新角色', description: '允许更新角色信息' }, { code: 'role:delete', resource: 'role', action: 'delete', name: '删除角色', description: '允许删除角色' }, { code: 'role:assign', resource: 'role', action: 'assign', name: '分配角色', description: '允许给用户分配角色' }, // 权限管理 { code: 'permission:read', resource: 'permission', action: 'read', name: '查看权限', description: '允许查看权限列表' }, // 菜单管理 { code: 'menu:read', resource: 'menu', action: 'read', name: '查看菜单', description: '允许查看菜单列表' }, // 租户管理 { code: 'tenant:create', resource: 'tenant', action: 'create', name: '创建租户', description: '允许创建租户' }, { code: 'tenant:read', resource: 'tenant', action: 'read', name: '查看租户', description: '允许查看租户列表' }, { code: 'tenant:update', resource: 'tenant', action: 'update', name: '更新租户', description: '允许更新租户信息' }, { code: 'tenant:delete', resource: 'tenant', action: 'delete', name: '删除租户', description: '允许删除租户' }, // 活动管理 { code: 'contest:create', resource: 'contest', action: 'create', name: '创建活动', description: '允许创建活动' }, { code: 'contest:read', resource: 'contest', action: 'read', name: '查看活动', description: '允许查看活动列表' }, { code: 'contest:update', resource: 'contest', action: 'update', name: '更新活动', description: '允许更新活动信息' }, { code: 'contest:delete', resource: 'contest', action: 'delete', name: '删除活动', description: '允许删除活动' }, { code: 'contest:publish', resource: 'contest', action: 'publish', name: '发布活动', description: '允许发布活动' }, { code: 'contest:finish', resource: 'contest', action: 'finish', name: '结束活动', description: '允许结束活动' }, // 评审规则 { code: 'review-rule:create', resource: 'review-rule', action: 'create', name: '创建评审规则', description: '允许创建评审规则' }, { code: 'review-rule:read', resource: 'review-rule', action: 'read', name: '查看评审规则', description: '允许查看评审规则' }, { code: 'review-rule:update', resource: 'review-rule', action: 'update', name: '更新评审规则', description: '允许更新评审规则' }, { code: 'review-rule:delete', resource: 'review-rule', action: 'delete', name: '删除评审规则', description: '允许删除评审规则' }, // 评委管理 { code: 'judge:create', resource: 'judge', action: 'create', name: '添加评委', description: '允许添加评委' }, { code: 'judge:read', resource: 'judge', action: 'read', name: '查看评委', description: '允许查看评委列表' }, { code: 'judge:update', resource: 'judge', action: 'update', name: '更新评委', description: '允许更新评委信息' }, { code: 'judge:delete', resource: 'judge', action: 'delete', name: '删除评委', description: '允许删除评委' }, { code: 'judge:assign', resource: 'judge', action: 'assign', name: '分配评委', description: '允许为活动分配评委' }, // 报名管理 { code: 'registration:read', resource: 'registration', action: 'read', name: '查看报名', description: '允许查看报名记录' }, { code: 'registration:approve', resource: 'registration', action: 'approve', name: '审核报名', description: '允许审核报名' }, // 作品管理 { code: 'work:read', resource: 'work', action: 'read', name: '查看作品', description: '允许查看参赛作品' }, // 公告管理 { code: 'notice:create', resource: 'notice', action: 'create', name: '创建公告', description: '允许创建活动公告' }, { code: 'notice:read', resource: 'notice', action: 'read', name: '查看公告', description: '允许查看活动公告' }, { code: 'notice:update', resource: 'notice', action: 'update', name: '更新公告', description: '允许更新公告信息' }, { code: 'notice:delete', resource: 'notice', action: 'delete', name: '删除公告', description: '允许删除公告' }, // 系统管理 { code: 'dict:create', resource: 'dict', action: 'create', name: '创建字典', description: '允许创建新字典' }, { code: 'dict:read', resource: 'dict', action: 'read', name: '查看字典', description: '允许查看字典列表和详情' }, { code: 'dict:update', resource: 'dict', action: 'update', name: '更新字典', description: '允许更新字典信息' }, { code: 'dict:delete', resource: 'dict', action: 'delete', name: '删除字典', description: '允许删除字典' }, { code: 'config:create', resource: 'config', action: 'create', name: '创建配置', description: '允许创建新配置' }, { code: 'config:read', resource: 'config', action: 'read', name: '查看配置', description: '允许查看配置列表和详情' }, { code: 'config:update', resource: 'config', action: 'update', name: '更新配置', description: '允许更新配置信息' }, { code: 'config:delete', resource: 'config', action: 'delete', name: '删除配置', description: '允许删除配置' }, { code: 'log:read', resource: 'log', action: 'read', name: '查看日志', description: '允许查看系统日志' }, { code: 'log:delete', resource: 'log', action: 'delete', name: '删除日志', description: '允许删除系统日志' }, ]; async function initAdmin() { try { console.log('🚀 开始初始化超级管理员...\n'); // 1. 获取或创建超级租户 console.log('🏢 步骤 1: 获取超级租户...'); let superTenant = await prisma.tenant.findFirst({ where: { isSuper: 1, validState: 1 } }); if (!superTenant) { console.log(' 未找到超级租户,正在创建...'); superTenant = await prisma.tenant.create({ data: { name: '超级租户', code: 'super', isSuper: 1, validState: 1, } }); console.log(` ✓ 创建超级租户: ${superTenant.name} (${superTenant.code})`); } else { console.log(` ✓ 找到超级租户: ${superTenant.name} (ID: ${superTenant.id})`); } const tenantId = superTenant.id; // 2. 创建权限 console.log('\n📝 步骤 2: 创建基础权限...'); const createdPermissions: any[] = []; for (const perm of permissions) { // 使用 tenantId + code 作为唯一约束 let permission = await prisma.permission.findFirst({ where: { tenantId, code: perm.code } }); if (permission) { permission = await prisma.permission.update({ where: { id: permission.id }, data: { ...perm, tenantId } }); } else { permission = await prisma.permission.create({ data: { ...perm, tenantId, validState: 1 } }); } createdPermissions.push(permission); } console.log(` ✓ 共创建/更新 ${createdPermissions.length} 个权限`); // 3. 创建超级管理员角色 console.log('\n👤 步骤 3: 创建超级管理员角色...'); let adminRole = await prisma.role.findFirst({ where: { tenantId, code: 'super_admin' } }); if (adminRole) { adminRole = await prisma.role.update({ where: { id: adminRole.id }, data: { name: '超级管理员', description: '拥有系统所有权限的超级管理员角色', } }); console.log(` ✓ 更新角色: ${adminRole.name}`); } else { adminRole = await prisma.role.create({ data: { tenantId, name: '超级管理员', code: 'super_admin', description: '拥有系统所有权限的超级管理员角色', validState: 1, } }); console.log(` ✓ 创建角色: ${adminRole.name}`); } // 4. 分配权限给角色 console.log('\n🔗 步骤 4: 分配权限给角色...'); // 先获取已有的角色权限 const existingRolePermissions = await prisma.rolePermission.findMany({ where: { roleId: adminRole.id }, select: { permissionId: true } }); const existingPermissionIds = new Set(existingRolePermissions.map(rp => rp.permissionId)); let addedCount = 0; for (const perm of createdPermissions) { if (!existingPermissionIds.has(perm.id)) { await prisma.rolePermission.create({ data: { roleId: adminRole.id, permissionId: perm.id, } }); addedCount++; } } console.log(` ✓ 新增 ${addedCount} 个权限分配`); // 5. 创建 admin 用户 console.log('\n👤 步骤 5: 创建 admin 用户...'); const password = `admin@${superTenant.code}`; const hashedPassword = await bcrypt.hash(password, 10); let adminUser = await prisma.user.findFirst({ where: { tenantId, username: 'admin' } }); if (adminUser) { adminUser = await prisma.user.update({ where: { id: adminUser.id }, data: { password: hashedPassword, nickname: '超级管理员', validState: 1, } }); console.log(` ✓ 更新用户: ${adminUser.username}`); } else { adminUser = await prisma.user.create({ data: { tenantId, username: 'admin', password: hashedPassword, nickname: '超级管理员', validState: 1, } }); console.log(` ✓ 创建用户: ${adminUser.username}`); } // 6. 给用户分配角色 console.log('\n🔗 步骤 6: 分配角色给用户...'); const existingUserRole = await prisma.userRole.findFirst({ where: { userId: adminUser.id, roleId: adminRole.id } }); if (!existingUserRole) { await prisma.userRole.create({ data: { userId: adminUser.id, roleId: adminRole.id, } }); console.log(` ✓ 分配角色: ${adminRole.name}`); } else { console.log(` ✓ 角色已分配: ${adminRole.name}`); } // 7. 输出结果 console.log('\n' + '='.repeat(50)); console.log('🎉 超级管理员初始化完成!'); console.log('='.repeat(50)); console.log(` 租户编码: ${superTenant.code}`); console.log(` 用户名: admin`); console.log(` 密码: ${password}`); console.log(` 角色: ${adminRole.name}`); console.log(` 权限数量: ${createdPermissions.length}`); console.log('='.repeat(50)); console.log('\n💡 提示: 请运行以下命令初始化菜单:'); console.log(' npm run init:menus'); } catch (error) { console.error('❌ 初始化失败:', error); throw error; } finally { await prisma.$disconnect(); } } // 执行初始化 initAdmin() .then(() => { console.log('\n✅ 初始化脚本执行完成!'); process.exit(0); }) .catch((error) => { console.error('\n💥 初始化脚本执行失败:', error); process.exit(1); });