gongxiangp2/scripts/migrate-role-enum-safe.ts
chenpei ea9076df45 feat: 实现统一的下载错误处理系统并修复产品全案数据库Schema
- 创建统一的下载错误处理模块 (lib/download-errors.ts)
- 实现13种错误类型分类和中文错误消息
- 后端统一使用 createDownloadError 创建标准化错误响应
- 前端统一使用 parseDownloadError 解析错误并显示
- 修复正式系统数据库Schema,添加产品全案相关字段和表
- 执行数据库迁移:添加 task_no, task_status, task_fetched_at 字段
- 创建 material_assets, api_keys, api_call_logs 表
2026-01-05 17:52:42 +08:00

166 lines
5.7 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.

/**
* 阶段四:角色枚举扩展迁移脚本
*
* 功能:
* 1. 将现有 ADMIN 角色迁移为 SYSTEM_ADMIN(可选,建议保留ADMIN以兼容)
* 2. 验证角色数据
*
* 使用方法:
* DATABASE_URL="your_database_url" npx tsx scripts/migrate-role-enum-safe.ts
*/
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
async function migrateRoleEnum() {
console.log('========================================');
console.log('阶段四:角色枚举扩展迁移');
console.log('========================================\n');
try {
// 1. 检查当前用户角色分布
const totalUsers = await prisma.user.count();
const userRoleCount = await prisma.user.count({ where: { role: 'USER' } });
const adminRoleCount = await prisma.user.count({ where: { role: 'ADMIN' } });
console.log(`📊 当前用户角色分布:`);
console.log(` 总用户数: ${totalUsers}`);
console.log(` USER: ${userRoleCount}`);
console.log(` ADMIN: ${adminRoleCount}`);
// 2. 检查新角色是否已经存在(如果Schema已更新)
let deptAdminCount = 0;
let systemAdminCount = 0;
try {
// 尝试查询新角色(如果枚举已更新)
const deptAdminResult = await prisma.$queryRaw<Array<{ count: bigint }>>`
SELECT COUNT(*) as count FROM users WHERE role = 'DEPT_ADMIN'
`.catch(() => null);
const systemAdminResult = await prisma.$queryRaw<Array<{ count: bigint }>>`
SELECT COUNT(*) as count FROM users WHERE role = 'SYSTEM_ADMIN'
`.catch(() => null);
if (deptAdminResult) {
deptAdminCount = Number(deptAdminResult[0]?.count || 0);
}
if (systemAdminResult) {
systemAdminCount = Number(systemAdminResult[0]?.count || 0);
}
console.log(` DEPT_ADMIN: ${deptAdminCount}`);
console.log(` SYSTEM_ADMIN: ${systemAdminCount}`);
} catch (error) {
console.log(` ⚠️ 新角色枚举可能尚未添加到Schema(这是正常的)`);
}
// 3. 可选:将现有 ADMIN 角色迁移为 SYSTEM_ADMIN
// 注意:建议保留 ADMIN 角色以保持向后兼容
// 如果需要迁移,取消下面的注释
/*
if (adminRoleCount > 0) {
console.log(`\n🔧 迁移 ADMIN 角色为 SYSTEM_ADMIN...`);
console.log(` 注意:这会将 ${adminRoleCount} 个 ADMIN 用户迁移为 SYSTEM_ADMIN`);
// 使用原生SQL更新(因为Prisma可能不支持枚举值修改)
const result = await prisma.$executeRaw`
UPDATE users
SET role = 'SYSTEM_ADMIN'::text::role
WHERE role = 'ADMIN'
`;
console.log(` ✅ 已迁移 ${result} 个用户`);
} else {
console.log(`\n✅ 没有需要迁移的 ADMIN 用户`);
}
*/
console.log(`\n💡 建议:`);
console.log(` 1. 保留 ADMIN 角色以保持向后兼容`);
console.log(` 2. 新功能使用 SYSTEM_ADMIN 和 DEPT_ADMIN`);
console.log(` 3. 在代码中使用兼容性检查(ADMIN 视为 SYSTEM_ADMIN)`);
// 4. 验证迁移结果
console.log('\n✅ 验证迁移结果...');
const finalStats = {
total: await prisma.user.count(),
USER: await prisma.user.count({ where: { role: 'USER' } }),
ADMIN: await prisma.user.count({ where: { role: 'ADMIN' } }),
};
// 尝试获取新角色统计(如果存在)
try {
const newDeptAdmin = await prisma.$queryRaw<Array<{ count: bigint }>>`
SELECT COUNT(*) as count FROM users WHERE role = 'DEPT_ADMIN'
`.catch(() => null);
const newSystemAdmin = await prisma.$queryRaw<Array<{ count: bigint }>>`
SELECT COUNT(*) as count FROM users WHERE role = 'SYSTEM_ADMIN'
`.catch(() => null);
if (newDeptAdmin) {
(finalStats as any).DEPT_ADMIN = Number(newDeptAdmin[0]?.count || 0);
}
if (newSystemAdmin) {
(finalStats as any).SYSTEM_ADMIN = Number(newSystemAdmin[0]?.count || 0);
}
} catch (error) {
// 忽略,枚举可能尚未更新
}
console.log(` 总用户数: ${finalStats.total}`);
console.log(` USER: ${finalStats.USER}`);
console.log(` ADMIN: ${finalStats.ADMIN}`);
if ((finalStats as any).DEPT_ADMIN !== undefined) {
console.log(` DEPT_ADMIN: ${(finalStats as any).DEPT_ADMIN}`);
}
if ((finalStats as any).SYSTEM_ADMIN !== undefined) {
console.log(` SYSTEM_ADMIN: ${(finalStats as any).SYSTEM_ADMIN}`);
}
// 5. 检查数据完整性
console.log('\n🔍 检查数据完整性...');
// 检查是否有无效角色(如果枚举已更新,可以检查)
const allUsers = await prisma.user.findMany({
select: { id: true, email: true, role: true },
});
const validRoles = ['USER', 'ADMIN', 'DEPT_ADMIN', 'SYSTEM_ADMIN'];
const invalidRoles = allUsers.filter(
u => !validRoles.includes(u.role as string)
);
if (invalidRoles.length > 0) {
console.log(` ⚠️ 发现 ${invalidRoles.length} 个用户使用了无效角色:`);
invalidRoles.forEach(u => {
console.log(` ${u.email}: ${u.role}`);
});
} else {
console.log(' ✅ 所有用户角色有效');
}
console.log('\n========================================');
console.log('✅ 角色枚举扩展迁移完成');
console.log('========================================\n');
} catch (error) {
console.error('\n❌ 迁移失败:', error);
throw error;
}
}
migrateRoleEnum()
.catch((error) => {
console.error('迁移脚本执行失败:', error);
process.exit(1);
})
.finally(async () => {
await prisma.$disconnect();
});