library-picturebook-activity/backend/scripts/init-guangdong-library.ts

194 lines
7.2 KiB
TypeScript
Raw Normal View History

/**
* 广 -
*
* :
* npx ts-node -r tsconfig-paths/register scripts/init-guangdong-library.ts
*
* :
* 1. 广library
* 2.
* 3.
* 4.
*/
import { PrismaClient } from '@prisma/client';
import * as bcrypt from 'bcrypt';
const prisma = new PrismaClient();
async function main() {
console.log('开始初始化广东省图数据...\n');
// 1. 创建租户
const tenantCode = 'gdlib';
let tenant = await prisma.tenant.findUnique({ where: { code: tenantCode } });
if (tenant) {
console.log(`租户 ${tenantCode} 已存在 (ID: ${tenant.id}),跳过创建`);
} else {
tenant = await prisma.tenant.create({
data: {
name: '广东省立中山图书馆',
code: tenantCode,
tenantType: 'library',
description: '广东省图少儿绘本创作活动主办方',
isSuper: 0,
validState: 1,
},
});
console.log(`创建租户: ${tenant.name} (ID: ${tenant.id})`);
}
const tenantId = tenant.id;
// 2. 创建权限
const permissions = [
// 活动管理
{ 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: 'registration:approve', resource: 'registration', action: 'approve', name: '审核报名', description: '允许审核报名' },
{ code: 'registration:read', resource: 'registration', action: 'read', name: '查看报名', description: '允许查看报名记录' },
// 评委管理
{ code: 'judge:read', resource: 'judge', action: 'read', name: '查看评委', description: '允许查看评委' },
{ code: 'judge:create', resource: 'judge', action: 'create', name: '添加评委', description: '允许添加评委' },
{ code: 'judge:assign', resource: 'judge', action: 'assign', name: '分配评委', description: '允许分配评委' },
// 评审规则
{ code: 'review-rule:read', resource: 'review-rule', action: 'read', name: '查看评审规则', description: '允许查看评审规则' },
{ code: 'review-rule:create', resource: 'review-rule', action: 'create', name: '创建评审规则', description: '允许创建评审规则' },
// 成果发布
{ code: 'result:read', resource: 'result', action: 'read', name: '查看成果', description: '允许查看活动成果' },
{ code: 'result:publish', resource: 'result', action: 'publish', name: '发布成果', description: '允许发布活动成果' },
// 公告
{ code: 'notice:create', resource: 'notice', action: 'create', name: '创建公告', description: '允许创建活动公告' },
{ code: 'notice:read', resource: 'notice', action: 'read', name: '查看公告', description: '允许查看活动公告' },
// 用户管理
{ code: 'user:read', resource: 'user', action: 'read', name: '查看用户', description: '允许查看用户' },
{ code: 'user:create', resource: 'user', action: 'create', name: '创建用户', description: '允许创建用户' },
// 角色管理
{ code: 'role:read', resource: 'role', action: 'read', name: '查看角色', description: '允许查看角色' },
// 菜单
{ code: 'menu:read', resource: 'menu', action: 'read', name: '查看菜单', description: '允许查看菜单' },
];
const permissionIds: number[] = [];
for (const perm of permissions) {
const existing = await prisma.permission.findFirst({
where: { tenantId, code: perm.code },
});
if (existing) {
permissionIds.push(existing.id);
} else {
const created = await prisma.permission.create({
data: { ...perm, tenantId, validState: 1 },
});
permissionIds.push(created.id);
}
}
console.log(`权限已创建/确认: ${permissionIds.length}`);
// 3. 创建管理员角色
let adminRole = await prisma.role.findFirst({
where: { tenantId, code: 'tenant_admin' },
});
if (!adminRole) {
adminRole = await prisma.role.create({
data: {
tenantId,
name: '机构管理员',
code: 'tenant_admin',
description: '广东省图机构管理员,管理活动和报名',
validState: 1,
},
});
console.log(`创建角色: ${adminRole.name}`);
}
// 分配所有权限给管理员角色
for (const permId of permissionIds) {
const existing = await prisma.rolePermission.findFirst({
where: { roleId: adminRole.id, permissionId: permId },
});
if (!existing) {
await prisma.rolePermission.create({
data: { roleId: adminRole.id, permissionId: permId },
});
}
}
console.log(`角色权限已分配`);
// 4. 创建管理员账号
const adminUsername = 'admin';
let adminUser = await prisma.user.findFirst({
where: { tenantId, username: adminUsername },
});
if (!adminUser) {
const hashedPassword = await bcrypt.hash('admin@gdlib', 10);
adminUser = await prisma.user.create({
data: {
tenantId,
username: adminUsername,
password: hashedPassword,
nickname: '广东省图管理员',
userSource: 'admin_created',
status: 'enabled',
validState: 1,
roles: {
create: [{ roleId: adminRole.id }],
},
},
});
console.log(`创建管理员: ${adminUsername} / admin@gdlib`);
} else {
console.log(`管理员 ${adminUsername} 已存在`);
}
// 5. 分配菜单(活动管理 + 系统管理)
const menuNames = ['活动管理', '系统管理'];
const menus = await prisma.menu.findMany({
where: { name: { in: menuNames }, parentId: null },
include: { children: true },
});
for (const menu of menus) {
// 分配父菜单
const existing = await prisma.tenantMenu.findFirst({
where: { tenantId, menuId: menu.id },
});
if (!existing) {
await prisma.tenantMenu.create({
data: { tenantId, menuId: menu.id },
});
}
// 分配子菜单
for (const child of menu.children || []) {
const childExisting = await prisma.tenantMenu.findFirst({
where: { tenantId, menuId: child.id },
});
if (!childExisting) {
await prisma.tenantMenu.create({
data: { tenantId, menuId: child.id },
});
}
}
}
console.log(`菜单已分配: ${menuNames.join(', ')}`);
console.log('\n广东省图初始化完成!');
console.log(`登录地址: /${tenantCode}/login`);
console.log(`账号: admin / admin@gdlib`);
}
main()
.catch((e) => {
console.error('初始化失败:', e);
process.exit(1);
})
.finally(async () => {
await prisma.$disconnect();
});