feat: initial release v0.3.0

This commit is contained in:
saturn
2026-03-08 03:15:27 +08:00
commit 881ed44996
1311 changed files with 225407 additions and 0 deletions

188
scripts/diagnose-project.ts Normal file
View File

@@ -0,0 +1,188 @@
/**
* 诊断项目任务状态
* 运行: npx tsx scripts/diagnose-project.ts <projectId>
*/
import { config } from 'dotenv'
config()
import { prisma } from '../src/lib/prisma'
async function diagnoseProject(projectId: string) {
console.log(`🔍 诊断项目: ${projectId}\n`)
// 1. 检查项目是否存在
console.log('1⃣ 项目基本信息:')
const project = await prisma.project.findUnique({
where: { id: projectId },
include: {
novelPromotionData: true
}
})
if (!project) {
console.log(' ❌ 项目不存在')
process.exit(1)
}
console.log(` 名称: ${project.name}`)
console.log(` 模式: ${project.mode}`)
console.log(` 用户ID: ${project.userId}`)
// 2. 检查 NovelPromotionProject
console.log('\n2⃣ 小说推广项目配置:')
const novelData = project.novelPromotionData
if (!novelData) {
console.log(' ❌ novelPromotionData 未创建')
} else {
console.log(` ID: ${novelData.id}`)
console.log(` 视频比例: ${novelData.videoRatio || '未设置'}`)
console.log(` 画风提示: ${novelData.artStylePrompt || '未设置'}`)
}
// 3. 检查场景和场景图片
console.log('\n3⃣ 场景资产:')
const novelProjectId = novelData?.id
if (!novelProjectId) {
console.log(' ❌ 无法获取 novelPromotionProject ID')
process.exit(1)
}
const locations = await prisma.novelPromotionLocation.findMany({
where: { novelPromotionProjectId: novelProjectId },
include: {
images: {
orderBy: { imageIndex: 'asc' }
}
}
})
console.log(` 场景数量: ${locations.length}`)
for (const loc of locations) {
console.log(`\n 📍 ${loc.name} (${loc.id})`)
console.log(` 图片数量: ${loc.images?.length || 0}`)
for (const img of loc.images || []) {
console.log(` - [${img.imageIndex}] imageUrl: ${img.imageUrl || 'null'}`)
console.log(` isSelected: ${img.isSelected}`)
console.log(` description: ${img.description || 'null'}`)
// 检查 MediaObject
if (img.imageUrl) {
const media = await prisma.mediaObject.findFirst({
where: {
OR: [
{ storageKey: img.imageUrl },
{ storageKey: { contains: img.imageUrl.split('/').pop() || '' } }
]
}
})
if (media) {
console.log(` ✅ MediaObject: ${media.publicId}`)
} else {
console.log(` ⚠️ 未找到 MediaObject`)
}
}
}
}
// 4. 检查最近的任务
console.log('\n4⃣ 最近的任务:')
const tasks = await prisma.task.findMany({
where: { projectId },
orderBy: { createdAt: 'desc' },
take: 10
})
console.log(` 任务数量: ${tasks.length}`)
for (const task of tasks) {
console.log(`\n 📝 ${task.type} (${task.id})`)
console.log(` 状态: ${task.status}`)
console.log(` 目标: ${task.targetType} / ${task.targetId}`)
console.log(` 创建时间: ${task.createdAt}`)
console.log(` 更新时间: ${task.updatedAt}`)
if (task.errorMessage || task.errorCode) {
console.log(` ❌ 错误码: ${task.errorCode || 'N/A'}`)
console.log(` ❌ 错误信息: ${task.errorMessage?.substring(0, 200) || 'N/A'}`)
}
// 获取任务事件
const events = await prisma.taskEvent.findMany({
where: { taskId: task.id },
orderBy: { createdAt: 'desc' },
take: 3
})
if (events.length > 0) {
console.log(` 最近事件:`)
for (const event of events) {
console.log(` - ${event.eventType}: ${JSON.stringify(event.payload).substring(0, 100)}`)
}
}
}
// 5. 检查 Worker 队列状态
console.log('\n5⃣ 检查 Worker 配置:')
console.log(` REDIS_HOST: ${process.env.REDIS_HOST || '未设置'}`)
console.log(` REDIS_PORT: ${process.env.REDIS_PORT || '未设置'}`)
// 尝试连接 Redis
try {
const { Redis } = await import('ioredis')
const redis = new Redis({
host: process.env.REDIS_HOST || 'localhost',
port: parseInt(process.env.REDIS_PORT || '6379'),
maxRetriesPerRequest: 3,
connectTimeout: 5000
})
const pingResult = await redis.ping()
console.log(` ✅ Redis 连接: ${pingResult}`)
// 检查 BullMQ 队列
const queueKeys = await redis.keys('bull:*:id')
console.log(` BullMQ 队列数量: ${queueKeys.length}`)
for (const key of queueKeys.slice(0, 5)) {
const queueName = key.replace('bull:', '').replace(':id', '')
const jobCounts = await redis.hgetall(`bull:${queueName}:id`)
console.log(` - ${queueName}`)
}
redis.disconnect()
} catch (error) {
console.log(` ❌ Redis 连接失败:`, error)
}
// 6. 检查模型配置
console.log('\n6⃣ 检查用户模型配置:')
const userPreference = await prisma.userPreference.findUnique({
where: { userId: project.userId }
})
if (!userPreference) {
console.log(' ❌ 用户偏好配置不存在')
} else {
console.log(` 角色模型: ${userPreference.characterModel || '未设置'}`)
console.log(` 场景模型: ${userPreference.locationModel || '未设置'}`)
console.log(` 视频模型: ${userPreference.videoModel || '未设置'}`)
console.log(` 编辑模型: ${userPreference.editModel || '未设置'}`)
console.log(` 口型同步模型: ${userPreference.lipSyncModel || '未设置'}`)
console.log(` 分析模型: ${userPreference.analysisModel || '未设置'}`)
}
console.log('\n✨ 诊断完成!')
await prisma.$disconnect()
}
const projectId = process.argv[2]
if (!projectId) {
console.log('用法: npx tsx scripts/diagnose-project.ts <projectId>')
console.log('示例: npx tsx scripts/diagnose-project.ts fae709e9-9215-4b3f-9f53-dad871f09896')
process.exit(1)
}
diagnoseProject(projectId).catch(console.error)