import { PrismaClient } from '@prisma/client'; import { logger } from '../src/utils/logger'; const prisma = new PrismaClient(); /** * 数据清洗脚本:为所有没有封面的笔记本自动补上相关课程的封面 */ async function backfillNotebooksCover() { try { console.log('=== 开始清洗笔记本封面数据 ===\n'); // 获取所有没有封面的笔记本 const notebooks = await prisma.notebook.findMany({ where: { OR: [ { coverImage: null }, { coverImage: '' }, ], }, }); console.log(`找到 ${notebooks.length} 个需要补封面的笔记本\n`); let successCount = 0; let failCount = 0; for (const notebook of notebooks) { let coverImage: string | null = null; try { // 方法1:从关联笔记的课程中获取 const firstNote = await prisma.note.findFirst({ where: { notebookId: notebook.id, courseId: { not: null }, }, orderBy: { createdAt: 'asc' }, include: { course: { select: { coverImage: true, }, }, }, }); if (firstNote?.course?.coverImage) { coverImage = firstNote.course.coverImage; console.log(`✅ [${notebook.id}] 从关联笔记的课程获取封面: ${coverImage}`); } else if (firstNote?.courseId) { // 备用方案:单独查询课程 const course = await prisma.course.findUnique({ where: { id: firstNote.courseId }, select: { coverImage: true }, }); if (course?.coverImage) { coverImage = course.coverImage; console.log(`✅ [${notebook.id}] 从课程 ${firstNote.courseId} 获取封面(备用方案): ${coverImage}`); } } // 方法2:如果方法1失败,通过课程名称匹配 if (!coverImage) { const courseName = notebook.title .replace(/《/g, '') .replace(/》/g, '') .trim(); if (courseName) { // 先尝试精确匹配 let matchingCourse = await prisma.course.findFirst({ where: { title: courseName }, select: { id: true, title: true, coverImage: true }, }); // 如果精确匹配失败,尝试包含匹配 if (!matchingCourse) { matchingCourse = await prisma.course.findFirst({ where: { title: { contains: courseName, }, }, select: { id: true, title: true, coverImage: true }, }); } if (matchingCourse?.coverImage) { coverImage = matchingCourse.coverImage; console.log(`✅ [${notebook.id}] 通过课程名称匹配获取封面: ${matchingCourse.title} -> ${coverImage}`); } } } // 更新笔记本封面 if (coverImage) { await prisma.notebook.update({ where: { id: notebook.id }, data: { coverImage }, }); successCount++; } else { console.log(`⚠️ [${notebook.id}] "${notebook.title}" 无法找到匹配的课程封面`); failCount++; } } catch (error) { console.error(`❌ [${notebook.id}] 处理失败:`, error); failCount++; } } console.log(`\n=== 清洗完成 ===`); console.log(`成功: ${successCount} 个`); console.log(`失败: ${failCount} 个`); } catch (error) { console.error('脚本执行失败:', error); } finally { await prisma.$disconnect(); } } backfillNotebooksCover();