001project_wildgrowth/backend/scripts/update-notebook-covers.ts

165 lines
5.0 KiB
TypeScript
Raw Normal View History

2026-02-11 15:26:03 +08:00
/**
*
*
*
* 使
* npx ts-node scripts/update-notebook-covers.ts
*/
import prisma from '../src/utils/prisma';
// ✅ 辅助函数:从笔记本标题中提取课程名称(移除书名号)
function extractCourseNameFromTitle(notebookTitle: string): string {
// 移除书名号《》和多余的空格
return notebookTitle
.replace(/《/g, '')
.replace(/》/g, '')
.trim();
}
async function updateNotebookCovers() {
try {
console.log('🚀 开始更新笔记本封面...\n');
// 获取所有封面为空的笔记本
const notebooks = await prisma.notebook.findMany({
where: {
OR: [
{ coverImage: null },
{ coverImage: '' },
],
},
include: {
_count: {
select: { notes: true },
},
},
});
console.log(`📚 找到 ${notebooks.length} 个需要更新封面的笔记本\n`);
let updatedCount = 0;
let skippedCount = 0;
for (const notebook of notebooks) {
console.log(`📖 处理笔记本: ${notebook.title} (ID: ${notebook.id})`);
console.log(` - 当前封面: ${notebook.coverImage || 'null'}`);
console.log(` - 笔记数量: ${notebook._count.notes}`);
let coverImage: string | null = null;
let source = '';
// 方法1查找该笔记本的第一个有课程关联的笔记
const firstNote = await prisma.note.findFirst({
where: {
notebookId: notebook.id,
courseId: { not: null },
},
orderBy: { createdAt: 'asc' },
include: {
course: {
select: {
id: true,
title: true,
coverImage: true,
},
},
},
});
if (firstNote?.course?.coverImage) {
// ✅ 方法1成功从笔记关联的课程获取封面
coverImage = firstNote.course.coverImage;
source = `笔记关联的课程: ${firstNote.course.title} (ID: ${firstNote.course.id})`;
} else if (firstNote?.courseId) {
// 笔记有 courseId但课程没有封面单独查询
const course = await prisma.course.findUnique({
where: { id: firstNote.courseId },
select: { coverImage: true, title: true },
});
if (course?.coverImage) {
coverImage = course.coverImage;
source = `课程查询: ${course.title || firstNote.courseId}`;
}
}
// ✅ 方法2如果方法1失败尝试通过课程名称匹配处理历史数据
if (!coverImage && notebook._count.notes > 0) {
const courseName = extractCourseNameFromTitle(notebook.title);
console.log(` 🔍 尝试通过课程名称匹配: "${courseName}"`);
// 查找匹配的课程(标题包含课程名称)
const matchingCourse = await prisma.course.findFirst({
where: {
title: {
contains: courseName,
},
coverImage: { not: null },
},
select: {
id: true,
title: true,
coverImage: true,
},
});
if (matchingCourse?.coverImage) {
coverImage = matchingCourse.coverImage;
source = `课程名称匹配: ${matchingCourse.title} (ID: ${matchingCourse.id})`;
console.log(` ✅ 找到匹配的课程: ${matchingCourse.title}`);
}
}
// 更新笔记本封面
if (coverImage) {
await prisma.notebook.update({
where: { id: notebook.id },
data: { coverImage },
});
console.log(` ✅ 成功更新封面: ${coverImage}`);
console.log(` 📘 来源: ${source}\n`);
updatedCount++;
} else {
// 无法获取封面
const noteCount = await prisma.note.count({
where: { notebookId: notebook.id },
});
const noteWithCourseId = await prisma.note.count({
where: {
notebookId: notebook.id,
courseId: { not: null },
},
});
if (noteCount > 0) {
console.log(` ⚠️ 有 ${noteCount} 条笔记,其中 ${noteWithCourseId} 条有 courseId但无法获取封面\n`);
} else {
console.log(` ⚠️ 没有笔记\n`);
}
skippedCount++;
}
}
console.log('\n📊 更新完成:');
console.log(` ✅ 成功更新: ${updatedCount}`);
console.log(` ⚠️ 跳过: ${skippedCount}`);
} catch (error) {
console.error('❌ 更新失败:', error);
throw error;
} finally {
await prisma.$disconnect();
}
}
// 执行更新
updateNotebookCovers()
.then(() => {
console.log('\n✅ 脚本执行完成');
process.exit(0);
})
.catch((error) => {
console.error('\n❌ 脚本执行失败:', error);
process.exit(1);
});