| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158 |
- /**
- * 状态同步脚本:将现有数据从旧字段同步到 genStage
- * 使用 stage-manager 的安全函数
- * Run: npx ts-node prisma/sync-genstage.ts
- */
- import { PrismaClient } from '@prisma/client';
- import {
- BookGenStage,
- ChapterGenStage,
- bookStageIndex,
- chapterStageIndex,
- safeTransitionChapter,
- safeTransitionBook,
- checkAndRegressBook,
- tryAdvanceBook,
- } from '../src/modules/book-generator/stage-manager';
- const prisma = new PrismaClient();
- async function syncChapter(chapter: any): Promise<void> {
- const chapterAny = chapter as any;
- let targetStage: ChapterGenStage;
- // 根据旧字段计算新的 genStage
- if (chapterAny.videoStatus === 'completed') {
- targetStage = 'video_completed';
- } else if (chapterAny.videoStatus === 'generating') {
- targetStage = 'video_generating';
- } else if (chapterAny.audioStatus === 'completed') {
- targetStage = 'audio_completed';
- } else if (chapterAny.audioStatus === 'generating') {
- targetStage = 'audio_generating';
- } else if (chapterAny.contentStatus === 'completed') {
- targetStage = 'content_completed';
- } else if (chapterAny.contentStatus === 'generating') {
- targetStage = 'content_generating';
- } else if (chapterAny.status === 'completed') {
- // 只有章级别的 status
- targetStage = 'content_completed';
- } else if (chapterAny.status === 'failed' || chapterAny.contentStatus === 'failed' || chapterAny.audioStatus === 'failed' || chapterAny.videoStatus === 'failed') {
- targetStage = 'failed';
- } else {
- targetStage = 'idle';
- }
- const currentStage = chapterAny.genStage as ChapterGenStage;
- // 如果相同则跳过
- if (currentStage === targetStage) {
- console.log(` Chapter ${chapter.id}: 无需更新 (${currentStage})`);
- return;
- }
- // 比较阶段索引决定用哪个函数
- const currentIdx = chapterStageIndex(currentStage);
- const targetIdx = chapterStageIndex(targetStage);
- try {
- if (targetIdx > currentIdx) {
- // 前进用 safeTransitionChapter(内部已处理乐观锁)
- await safeTransitionChapter(chapter.id, currentStage, targetStage);
- } else {
- // 回退/同级也用 safeTransitionChapter(重新生成场景)
- await safeTransitionChapter(chapter.id, currentStage, targetStage);
- }
- console.log(` Chapter ${chapter.id}: ${currentStage} → ${targetStage}`);
- } catch (error: any) {
- // 并发冲突:跳过此记录
- console.log(` Chapter ${chapter.id}: 跳过 (${error.message})`);
- }
- }
- async function syncBook(book: any): Promise<void> {
- let targetStage: BookGenStage;
- switch (book.status) {
- case 'draft':
- targetStage = 'draft';
- break;
- case 'planning':
- targetStage = 'outline_completed';
- break;
- case 'generating':
- targetStage = inferBookGenStage(book);
- break;
- case 'completed':
- targetStage = inferBookGenStage(book);
- break;
- case 'failed':
- case 'interrupted':
- targetStage = 'failed';
- break;
- default:
- targetStage = 'draft';
- }
- const currentStage = (book.genStage || 'draft') as BookGenStage;
- if (currentStage === targetStage) {
- console.log(` Book ${book.id}: 无需更新 (${currentStage})`);
- return;
- }
- try {
- await safeTransitionBook(book.id, currentStage, targetStage);
- console.log(` Book ${book.id}: ${currentStage} → ${targetStage}`);
- } catch (error: any) {
- console.log(` Book ${book.id}: 跳过 (${error.message})`);
- }
- }
- function inferBookGenStage(book: any): BookGenStage {
- // 根据 chapters 状态推断
- const chapters = book.chapters || [];
- const hasVideo = chapters.some((c: any) => c.genStage === 'video_completed' || c.videoStatus === 'completed');
- if (hasVideo) return 'video_completed';
- const hasAudio = chapters.some((c: any) => c.genStage === 'audio_completed' || c.audioStatus === 'completed');
- if (hasAudio) return 'audio_completed';
- const hasContent = chapters.some((c: any) => c.genStage === 'content_completed' || c.contentStatus === 'completed');
- if (hasContent) return 'content_generating';
- return 'content_generating';
- }
- async function main() {
- console.log('开始状态同步...\n');
- // 同步 BookChapter
- console.log('=== 同步 BookChapter ===');
- const chapters = await prisma.bookChapter.findMany();
- for (const chapter of chapters) {
- await syncChapter(chapter);
- }
- console.log(`BookChapter 同步完成: ${chapters.length} 条\n`);
- // 同步 Book
- console.log('=== 同步 Book ===');
- const books = await prisma.book.findMany({ include: { chapters: true } });
- for (const book of books) {
- await syncBook(book);
- }
- console.log(`Book 同步完成: ${books.length} 条\n`);
- // 执行 Book 联动回退检查
- console.log('=== 检查 Book 联动回退 ===');
- for (const book of books) {
- await checkAndRegressBook(book.id);
- }
- console.log('✅ 状态同步完成!');
- }
- main()
- .catch(console.error)
- .finally(() => prisma.$disconnect());
|