93 lines
2.7 KiB
TypeScript
93 lines
2.7 KiB
TypeScript
|
|
/**
|
||
|
|
* 重新生成所有课程的封面图
|
||
|
|
* 使用方法: npx ts-node scripts/regenerate-all-covers.ts
|
||
|
|
*/
|
||
|
|
|
||
|
|
import { PrismaClient } from '@prisma/client';
|
||
|
|
import { generateCourseCover } from '../src/services/coverImageService';
|
||
|
|
import { logger } from '../src/utils/logger';
|
||
|
|
|
||
|
|
const prisma = new PrismaClient();
|
||
|
|
|
||
|
|
async function regenerateAllCovers() {
|
||
|
|
try {
|
||
|
|
// 1. 查找所有未删除的课程(包括已有封面的)
|
||
|
|
const allCourses = await prisma.course.findMany({
|
||
|
|
where: {
|
||
|
|
deletedAt: null,
|
||
|
|
title: {
|
||
|
|
not: '',
|
||
|
|
},
|
||
|
|
},
|
||
|
|
include: {
|
||
|
|
aiContentTask: {
|
||
|
|
select: {
|
||
|
|
generationStyle: true,
|
||
|
|
},
|
||
|
|
},
|
||
|
|
},
|
||
|
|
});
|
||
|
|
|
||
|
|
logger.info(`[RegenerateAllCovers] 找到 ${allCourses.length} 个课程,将重新生成所有封面`);
|
||
|
|
|
||
|
|
if (allCourses.length === 0) {
|
||
|
|
logger.info('[RegenerateAllCovers] 没有需要生成封面的课程');
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
// 2. 为每个课程重新生成封面
|
||
|
|
let successCount = 0;
|
||
|
|
let failCount = 0;
|
||
|
|
|
||
|
|
for (const course of allCourses) {
|
||
|
|
try {
|
||
|
|
const title = course.title || '未命名课程';
|
||
|
|
// 从任务中获取生成风格,如果没有则默认为 'full'
|
||
|
|
const style = (course.aiContentTask?.generationStyle as 'full' | 'essence' | 'one-page') || 'full';
|
||
|
|
|
||
|
|
logger.info(`[RegenerateAllCovers] 正在重新生成封面: ${course.id}, title="${title}", style=${style}`);
|
||
|
|
|
||
|
|
const coverImagePath = await generateCourseCover(
|
||
|
|
course.id,
|
||
|
|
title,
|
||
|
|
style
|
||
|
|
);
|
||
|
|
|
||
|
|
if (coverImagePath) {
|
||
|
|
// 更新数据库
|
||
|
|
await prisma.course.update({
|
||
|
|
where: { id: course.id },
|
||
|
|
data: { coverImage: coverImagePath },
|
||
|
|
});
|
||
|
|
logger.info(`[RegenerateAllCovers] ✅ 封面重新生成成功: ${course.id}, path=${coverImagePath}`);
|
||
|
|
successCount++;
|
||
|
|
} else {
|
||
|
|
logger.warn(`[RegenerateAllCovers] ⚠️ 封面生成返回空路径: ${course.id}`);
|
||
|
|
failCount++;
|
||
|
|
}
|
||
|
|
} catch (error: any) {
|
||
|
|
logger.error(`[RegenerateAllCovers] ❌ 为课程重新生成封面失败: ${course.id}`, error);
|
||
|
|
failCount++;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
logger.info(`[RegenerateAllCovers] 完成!成功: ${successCount}, 失败: ${failCount}`);
|
||
|
|
} catch (error: any) {
|
||
|
|
logger.error('[RegenerateAllCovers] 批量重新生成封面失败', error);
|
||
|
|
throw error;
|
||
|
|
} finally {
|
||
|
|
await prisma.$disconnect();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// 执行
|
||
|
|
regenerateAllCovers()
|
||
|
|
.then(() => {
|
||
|
|
console.log('✅ 批量重新生成封面完成');
|
||
|
|
process.exit(0);
|
||
|
|
})
|
||
|
|
.catch((error) => {
|
||
|
|
console.error('❌ 批量重新生成封面失败:', error);
|
||
|
|
process.exit(1);
|
||
|
|
});
|