library-picturebook-activity/backend/scripts/update-activity-menus.ts
2026-01-09 18:14:35 +08:00

157 lines
4.0 KiB
TypeScript
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.

import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
async function main() {
console.log('🔧 更新赛事活动菜单结构...\n');
// 1. 删除赛事管理下的赛事活动菜单
console.log('📝 步骤1: 移除赛事管理下的赛事活动菜单');
const oldActivityMenu = await prisma.menu.findFirst({
where: { path: '/contests/activities' }
});
if (oldActivityMenu) {
// 先删除租户菜单关联
await prisma.tenantMenu.deleteMany({
where: { menuId: oldActivityMenu.id }
});
// 再删除菜单
await prisma.menu.delete({
where: { id: oldActivityMenu.id }
});
console.log(' ✅ 已删除旧的赛事活动菜单');
} else {
console.log(' ⏭️ 旧菜单不存在,跳过');
}
// 2. 更新独立的赛事活动菜单(改为父菜单,不需要 component
console.log('\n📝 步骤2: 更新赛事活动为父级菜单');
let activityParent = await prisma.menu.findFirst({
where: { path: '/student-activities' }
});
if (activityParent) {
await prisma.menu.update({
where: { id: activityParent.id },
data: {
component: null, // 父菜单不需要组件
}
});
console.log(' ✅ 已更新为父级菜单');
} else {
// 如果不存在,创建它
activityParent = await prisma.menu.create({
data: {
name: '赛事活动',
path: '/student-activities',
component: null,
icon: 'TrophyOutlined',
permission: 'contest:activity:read',
sort: 10,
parentId: null,
validState: 1,
}
});
console.log(' ✅ 已创建父级菜单');
}
// 3. 创建三个子菜单
console.log('\n📝 步骤3: 创建子菜单');
const subMenus = [
{
name: '我的指导',
path: '/student-activities/guidance',
component: 'activities/Guidance',
permission: 'contest:activity:read',
sort: 1,
},
{
name: '评审作品',
path: '/student-activities/review',
component: 'activities/Review',
permission: 'contest:activity:read',
sort: 2,
},
{
name: '预设评语',
path: '/student-activities/comments',
component: 'activities/Comments',
permission: 'contest:activity:read',
sort: 3,
},
];
for (const menuData of subMenus) {
const existing = await prisma.menu.findFirst({
where: { path: menuData.path }
});
if (existing) {
console.log(` ⏭️ ${menuData.name} 已存在`);
} else {
await prisma.menu.create({
data: {
...menuData,
parentId: activityParent.id,
validState: 1,
}
});
console.log(` ✅ 已创建: ${menuData.name}`);
}
}
// 4. 为租户分配新菜单
console.log('\n📝 步骤4: 分配菜单给租户');
const tenants = await prisma.tenant.findMany({
select: { id: true, name: true }
});
const allMenus = await prisma.menu.findMany({
where: {
OR: [
{ id: activityParent.id },
{ parentId: activityParent.id }
]
}
});
for (const tenant of tenants) {
for (const menu of allMenus) {
const existing = await prisma.tenantMenu.findFirst({
where: { tenantId: tenant.id, menuId: menu.id }
});
if (!existing) {
await prisma.tenantMenu.create({
data: { tenantId: tenant.id, menuId: menu.id }
});
}
}
console.log(` ✅ 已分配给租户: ${tenant.name}`);
}
// 5. 显示最终菜单结构
console.log('\n📋 最终菜单结构:');
const finalMenus = await prisma.menu.findMany({
where: {
OR: [
{ id: activityParent.id },
{ parentId: activityParent.id }
]
},
orderBy: { sort: 'asc' }
});
finalMenus.forEach(m => {
const prefix = m.parentId ? ' ' : '';
console.log(`${prefix}- ${m.name} (${m.path})`);
});
console.log('\n✅ 菜单更新完成!');
}
main()
.catch(console.error)
.finally(() => prisma.$disconnect());