125 lines
3.8 KiB
TypeScript
125 lines
3.8 KiB
TypeScript
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();
|