- 创建统一的下载错误处理模块 (lib/download-errors.ts) - 实现13种错误类型分类和中文错误消息 - 后端统一使用 createDownloadError 创建标准化错误响应 - 前端统一使用 parseDownloadError 解析错误并显示 - 修复正式系统数据库Schema,添加产品全案相关字段和表 - 执行数据库迁移:添加 task_no, task_status, task_fetched_at 字段 - 创建 material_assets, api_keys, api_call_logs 表
166 lines
5.7 KiB
TypeScript
166 lines
5.7 KiB
TypeScript
/**
|
||
* 阶段四:角色枚举扩展迁移脚本
|
||
*
|
||
* 功能:
|
||
* 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();
|
||
});
|
||
|