SEED_REVIEW.md 8.2 KB

Menu Seed Files Review

✅ Overall Assessment: GOOD WITH RECOMMENDATIONS

Your seed files are structurally correct and will work with the database schema. However, there are some improvements recommended for production use.


📋 Current Status

✅ What's Working:

  • All required Prisma fields are present
  • Data types match schema definitions
  • Parent-child relationship logic is correct
  • Multi-pass insertion handles dependencies properly
  • MenuType enum values are valid (DIRECTORY, MENU, SUBMENU, BUTTON)
  • Error handling for circular dependencies exists

⚠️ What Needs Attention:

1. frontendAuth Field (Important for RBAC)

Current: All set to null

frontendAuth: null, // ❌ This is a unique field in your schema

Recommended: Derive from path or create unique identifiers

// In seed-menu.ts, update the create data:
frontendAuth: (seed.path, // Use path as unique identifier
  // OR create a dedicated field in menu-seeds.ts:
  {
    legacyId: 16,
    title: '系统用户',
    frontendAuth: '/system/users', // ✅ Add this
    // ... rest
  });

Why: Your OperationLog decorator uses frontendAuth to link backend operations to frontend menus. Without it, you can't track which menu triggered which operation.


2. Action Flags (Permissions)

Current: All set to 0 (no permissions)

canView: 0,    // ❌ User can't even view
canCreate: 0,
canUpdate: 0,
canDelete: 0,

Recommended: Set defaults based on menu type

// Helper function in seed-menu.ts:
function getDefaultPermissions(type: MenuType) {
  switch (type) {
    case 'DIRECTORY':
      return { canView: 1, canCreate: 0, canUpdate: 0, canDelete: 0 };
    case 'MENU':
      return { canView: 1, canCreate: 1, canUpdate: 1, canDelete: 1 };
    case 'SUBMENU':
      return { canView: 1, canCreate: 1, canUpdate: 1, canDelete: 1 };
    case 'BUTTON':
      return { canView: 0, canCreate: 1, canUpdate: 0, canDelete: 0 };
    default:
      return { canView: 0, canCreate: 0, canUpdate: 0, canDelete: 0 };
  }
}

// Then use it:
const permissions = getDefaultPermissions(seed.type);
const created = await prisma.menu.create({
  data: {
    // ... other fields
    ...permissions,
  },
});

Action Flag Values:

  • 0 = Not available
  • 1 = Available
  • 2 = Required (must be checked in frontend)

3. component_key Field

Current: All set to null

component_key: null, // ❌ Frontend might need this for routing

Recommended: Add to menu-seeds.ts and use it

// In menu-seeds.ts:
export interface SeedMenu {
  // ... existing fields
  componentKey?: string; // Add this
}

// Example data:
{
  legacyId: 16,
  title: '系统用户',
  componentKey: 'SystemUsers', // ✅ For Vue/React component routing
  // ... rest
}

// In seed-menu.ts:
component_key: seed.componentKey ?? null,

4. redirect Field Usage

Current: All set to null

redirect: null, // Might be needed for DIRECTORY types

Recommended: Set for DIRECTORY types to redirect to first child

// Example for directories:
{
  legacyId: 1,
  type: 'DIRECTORY',
  path: '/marketing',
  redirect: '/marketing/videos', // ✅ Redirect to first child
  // ... rest
}

🔧 Recommended Updates

Option 1: Quick Fix (Minimal Changes)

Update seed-menu.ts to derive frontendAuth from path:

const created = await prisma.menu.create({
  data: {
    parentId,
    title: seed.title,
    status: true,
    type: seed.type,
    order: seed.order,

    frontendAuth: seed.path, // ✅ Use path as unique identifier

    path: seed.path,
    name: seed.name,
    icon: seed.icon,
    redirect: null,
    component_key: null,
    meta: seed.meta ?? undefined,

    // ✅ Set default permissions based on type
    ...getDefaultPermissions(seed.type),
  },
});

Option 2: Complete Fix (Production-Ready)

  1. Update menu-seeds.ts interface:

    export interface SeedMenu {
    legacyId: number;
    legacyParentId: number | null;
    title: string;
    type: MenuType;
    name: string;
    path: string;
    icon: string | null;
    order: number;
    frontendAuth?: string; // ✅ Add
    componentKey?: string; // ✅ Add
    redirect?: string; // ✅ Add
    permissions?: {
    // ✅ Add
    canView?: number;
    canCreate?: number;
    canUpdate?: number;
    canDelete?: number;
    };
    meta?: Prisma.JsonValue;
    }
    
  2. Update seed data with these values:

    {
    legacyId: 16,
    title: '系统用户',
    type: 'MENU',
    name: 'systemUsers',
    path: '/system/users',
    frontendAuth: '/system/users',  // ✅
    componentKey: 'SystemUsers',     // ✅
    permissions: {                   // ✅
    canView: 1,
    canCreate: 1,
    canUpdate: 1,
    canDelete: 1,
    },
    // ... rest
    }
    
  3. Update seed-menu.ts to use these values:

    const defaultPerms = getDefaultPermissions(seed.type);
    
    const created = await prisma.menu.create({
    data: {
    parentId,
    title: seed.title,
    status: true,
    type: seed.type,
    order: seed.order,
    
    frontendAuth: seed.frontendAuth ?? seed.path,
    path: seed.path,
    name: seed.name,
    icon: seed.icon,
    redirect: seed.redirect ?? null,
    component_key: seed.componentKey ?? null,
    meta: seed.meta ?? undefined,
    
    canView: seed.permissions?.canView ?? defaultPerms.canView,
    canCreate: seed.permissions?.canCreate ?? defaultPerms.canCreate,
    canUpdate: seed.permissions?.canUpdate ?? defaultPerms.canUpdate,
    canDelete: seed.permissions?.canDelete ?? defaultPerms.canDelete,
    },
    });
    

🎯 Priority Recommendations

High Priority:

  1. ✅ Add frontendAuth values (use path if nothing else)
  2. ✅ Set proper action flags (at least canView: 1 for visible menus)

Medium Priority:

  1. ✅ Add componentKey for frontend routing
  2. ✅ Set redirect for DIRECTORY types

Low Priority:

  1. Consider adding more metadata to meta field
  2. Add validation in seed script

📊 Data Integrity Checks

Your seed script should pass these checks:

✅ Already Passing:

  • All parent IDs reference valid menus
  • No circular dependencies
  • All required fields present
  • MenuType enum values valid
  • Order numbers unique within parent

⚠️ Should Add:

  • frontendAuth uniqueness validation
  • Path format validation (/kebab-case)
  • Name format validation (camelCase)

🚀 Quick Test Script

Add this to verify your seed data before running:

// Add to seed-menu.ts before the main seeding loop:
function validateSeeds() {
  const paths = new Set<string>();
  const legacyIds = new Set<number>();

  for (const seed of MENU_SEEDS) {
    // Check unique paths
    if (paths.has(seed.path)) {
      throw new Error(`Duplicate path: ${seed.path}`);
    }
    paths.add(seed.path);

    // Check unique legacy IDs
    if (legacyIds.has(seed.legacyId)) {
      throw new Error(`Duplicate legacyId: ${seed.legacyId}`);
    }
    legacyIds.add(seed.legacyId);

    // Check parent exists (except for roots)
    if (seed.legacyParentId !== null) {
      const parentExists = MENU_SEEDS.some(
        (s) => s.legacyId === seed.legacyParentId,
      );
      if (!parentExists) {
        throw new Error(
          `Invalid parent ${seed.legacyParentId} for menu ${seed.legacyId}`,
        );
      }
    }
  }

  console.log('✅ Seed data validation passed');
}

// Call before seeding:
validateSeeds();

📝 Summary

Current State: Your seed files are functional and will work, but they create menus with minimal permissions and missing RBAC links.

Recommended State: Add the suggested fields to make the system production-ready with proper permissions and frontend integration.

Estimated Time:

  • Quick Fix: ~15 minutes
  • Complete Fix: ~1 hour

Risk Level: Low - All changes are additive, won't break existing structure


💡 Next Steps

  1. Decide between Quick Fix or Complete Fix
  2. Update seed files accordingly
  3. Test with: pnpm run prisma:seed:mysql (when DB is accessible)
  4. Verify in database that menus have proper permissions
  5. Test frontend routing with new component keys

Last Updated: November 17, 2025