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