| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127 |
- /**
- * 数据迁移脚本:将旧字段迁移到新的 genStage 字段
- * Run: npx ts-node prisma/migrate-genstage.ts
- */
- import { PrismaClient } from '@prisma/client';
- const prisma = new PrismaClient();
- async function migrate() {
- console.log('开始数据迁移...');
- // ========== Book 迁移 ==========
- console.log('\n迁移 Book 表...');
- const books = await prisma.book.findMany();
- let updatedBookCount = 0;
- for (const book of books) {
- let newGenStage: string;
- switch (book.status) {
- case 'draft':
- newGenStage = 'draft';
- break;
- case 'planning':
- newGenStage = 'outline_completed';
- break;
- case 'generating':
- // 需要检查子章节的实际状态
- newGenStage = await inferBookGenStageFromChapters(book.id);
- break;
- case 'completed':
- newGenStage = await inferBookGenStageFromChapters(book.id);
- break;
- case 'failed':
- case 'interrupted':
- newGenStage = 'failed';
- break;
- default:
- newGenStage = 'draft';
- }
- await prisma.book.update({
- where: { id: book.id },
- data: {
- genStage: newGenStage,
- failedStage: newGenStage === 'failed' ? book.status : undefined,
- },
- });
- updatedBookCount++;
- console.log(` Book ${book.id}: ${book.status} → ${newGenStage}`);
- }
- console.log(`Book 迁移完成: ${updatedBookCount} 条`);
- // ========== BookChapter 迁移 ==========
- console.log('\n迁移 BookChapter 表...');
- const chapters = await prisma.bookChapter.findMany();
- let updatedChapterCount = 0;
- for (const chapter of chapters) {
- let newGenStage: string;
- if (chapter.videoStatus === 'completed') {
- newGenStage = 'video_completed';
- } else if (chapter.videoStatus === 'generating') {
- newGenStage = 'video_generating';
- } else if (chapter.audioStatus === 'completed') {
- newGenStage = 'audio_completed';
- } else if (chapter.audioStatus === 'generating') {
- newGenStage = 'audio_generating';
- } else if (chapter.contentStatus === 'completed') {
- newGenStage = 'content_completed';
- } else if (chapter.contentStatus === 'generating') {
- newGenStage = 'content_generating';
- } else if (chapter.status === 'completed') {
- // 旧数据只有 status
- newGenStage = 'content_completed';
- } else if (chapter.status === 'failed' || chapter.contentStatus === 'failed' || chapter.audioStatus === 'failed' || chapter.videoStatus === 'failed') {
- newGenStage = 'failed';
- } else {
- newGenStage = 'idle';
- }
- await prisma.bookChapter.update({
- where: { id: chapter.id },
- data: { genStage: newGenStage },
- });
- updatedChapterCount++;
- console.log(` Chapter ${chapter.id}: status=${chapter.status}, content=${chapter.contentStatus}, audio=${chapter.audioStatus}, video=${chapter.videoStatus} → ${newGenStage}`);
- }
- console.log(`BookChapter 迁移完成: ${updatedChapterCount} 条`);
- console.log('\n✅ 数据迁移完成!');
- }
- /**
- * 根据子章节状态推断 Book 的 genStage
- */
- async function inferBookGenStageFromChapters(bookId: number): Promise<string> {
- const chapters = await prisma.bookChapter.findMany({
- where: { bookId, level: { gte: 1 }, parentId: 0 },
- });
- if (chapters.length === 0) return 'draft';
- // 检查是否有任意章节已达到 video_completed
- const hasVideoCompleted = chapters.some(c => c.genStage === 'video_completed' || c.videoStatus === 'completed');
- if (hasVideoCompleted) return 'video_completed';
- // 检查是否有章节已达到 audio_completed
- const hasAudioCompleted = chapters.some(c => c.genStage === 'audio_completed' || c.audioStatus === 'completed');
- if (hasAudioCompleted) return 'audio_completed';
- // 检查是否有章节已达到 content_completed
- const hasContentCompleted = chapters.some(c => c.genStage === 'content_completed' || c.contentStatus === 'completed');
- if (hasContentCompleted) return 'content_generating'; // 部分完成,仍在生成中
- return 'content_generating';
- }
- migrate()
- .catch(console.error)
- .finally(() => prisma.$disconnect());
|