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

165 lines
5.0 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 脚本:为所有笔记本自动更新封面(从关联笔记的课程中获取)
* ✅ 新增:支持通过课程名称匹配(处理历史数据问题)
*
* 使用方法:
* 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);
});