// 数据迁移脚本:将现有角色(reviewStatus 为空或默认 pending_review)标记为 synced // 背景:管理员审核 + Hermes 同步流程上线后,角色库过滤改为 reviewStatus='synced'。 // 现有角色是在审核流程上线前创建的,直接标记为 synced 以保持向后兼容。 // // 用法: node scripts/migrate-existing-roles-to-synced.js // // 安全说明: // - 仅迁移 status='running' 且 reviewStatus='pending_review' 的角色 // - 已有 reviewStatus(approved/synced/rejected/failed)的角色不受影响 // - 执行前会打印待迁移数量,需用户确认(除非传入 --yes 跳过确认) const prisma = require('../src/lib/prisma'); async function main() { const skipConfirm = process.argv.includes('--yes'); // 查找待迁移角色:status='running' 且 reviewStatus='pending_review' // 这些是审核流程上线前创建的角色 const candidates = await prisma.role.findMany({ where: { status: 'running', reviewStatus: 'pending_review', }, select: { id: true, displayName: true, createdAt: true }, }); console.log(`找到 ${candidates.length} 个待迁移角色(status=running 且 reviewStatus=pending_review)`); if (candidates.length === 0) { console.log('无需迁移'); await prisma.$disconnect(); return; } if (!skipConfirm) { console.log('\n待迁移角色列表(前 10 个):'); candidates.slice(0, 10).forEach((r, i) => { console.log(` ${i + 1}. ${r.displayName} (id=${r.id}, createdAt=${r.createdAt.toISOString()})`); }); if (candidates.length > 10) { console.log(` ... 还有 ${candidates.length - 10} 个`); } console.log('\n将这些角色标记为 synced(已同步)?此操作不可逆。'); console.log('确认请输入 yes,否则取消:'); const readline = require('readline'); const rl = readline.createInterface({ input: process.stdin, output: process.stdout }); const answer = await new Promise((resolve) => { rl.question('> ', (a) => { rl.close(); resolve(a.trim().toLowerCase()); }); }); if (answer !== 'yes') { console.log('已取消'); await prisma.$disconnect(); return; } } const result = await prisma.role.updateMany({ where: { status: 'running', reviewStatus: 'pending_review', }, data: { reviewStatus: 'synced', syncedAt: new Date(), }, }); console.log(`\n迁移完成:${result.count} 个角色已标记为 synced`); await prisma.$disconnect(); } main().catch((err) => { console.error('迁移失败:', err); process.exit(1); });