/** * 清理卡在30%的课程数据 * 使用方法:ts-node backend/scripts/cleanup-stuck-courses.ts */ import prisma from '../src/utils/prisma'; import * as dotenv from 'dotenv'; import path from 'path'; // 加载环境变量 dotenv.config({ path: path.join(__dirname, '../.env') }); async function cleanupStuckCourses() { try { console.log('🔍 查找卡在30%的课程...\n'); // 查找状态为generating且progress为0.3的课程 const stuckCourses = await prisma.course.findMany({ where: { generationStatus: 'generating', generationProgress: 0.3, }, include: { aiContentTask: { select: { id: true, status: true, suggestedTitle: true, }, }, }, }); console.log(`找到 ${stuckCourses.length} 个卡住的课程:\n`); if (stuckCourses.length === 0) { console.log('✅ 没有需要清理的课程'); await prisma.$disconnect(); return; } // 显示课程信息 stuckCourses.forEach((course, index) => { console.log(`${index + 1}. ${course.title}`); console.log(` Course ID: ${course.id}`); console.log(` Task ID: ${course.aiContentTask?.id || 'N/A'}`); console.log(` 创建时间: ${course.createdAt}`); console.log(''); }); // 确认删除 console.log('⚠️ 准备删除以上课程及其关联数据...\n'); let deletedCount = 0; let errorCount = 0; for (const course of stuckCourses) { try { // 1. 删除 UserCourse 关联 await prisma.userCourse.deleteMany({ where: { courseId: course.id, }, }); // 2. 删除 Course 记录 await prisma.course.delete({ where: { id: course.id, }, }); // 3. 删除 AIContentTask(如果存在) if (course.aiContentTaskId) { await prisma.aIPromptLog.deleteMany({ where: { taskId: course.aiContentTaskId, }, }); await prisma.aIContentTask.delete({ where: { id: course.aiContentTaskId, }, }); } deletedCount++; console.log(`✅ 已删除: ${course.title} (${course.id})`); } catch (error: any) { errorCount++; console.error(`❌ 删除失败: ${course.title} (${course.id}) - ${error.message}`); } } console.log('\n📊 清理结果:'); console.log(` ✅ 成功删除: ${deletedCount} 个课程`); if (errorCount > 0) { console.log(` ❌ 删除失败: ${errorCount} 个课程`); } await prisma.$disconnect(); } catch (error: any) { console.error('❌ 清理过程出错:', error); await prisma.$disconnect(); process.exit(1); } } // 运行清理 cleanupStuckCourses();