157 lines
4.0 KiB
TypeScript
157 lines
4.0 KiB
TypeScript
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());
|