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);
|
|||
|
|
});
|