001project_wildgrowth/backend/scripts/inspect-paragraphs-server.js

125 lines
4.4 KiB
JavaScript
Raw Permalink Normal View History

2026-02-11 15:26:03 +08:00
#!/usr/bin/env node
/**
* 排查段落间距对比 调用记录里 outline.suggestedContent node_slides.content.paragraphs
* 在服务器上执行需能连到数据库
* cd /var/www/wildgrowth-backend/backend && node scripts/inspect-paragraphs-server.js
* 本地 .env
* cd backend && node scripts/inspect-paragraphs-server.js
*/
const { PrismaClient } = require('@prisma/client');
const prisma = new PrismaClient();
async function main() {
const argId = process.argv[2] ? process.argv[2].trim() : null;
let task;
if (argId) {
// 先按 taskId 查,再按 courseId 查
task = await prisma.courseGenerationTask.findFirst({
where: { id: argId },
include: { course: { select: { id: true, title: true } } },
});
if (!task) {
task = await prisma.courseGenerationTask.findFirst({
where: { courseId: argId },
orderBy: { createdAt: 'desc' },
include: { course: { select: { id: true, title: true } } },
});
}
if (!task) {
console.log('未找到 taskId 或 courseId 为', argId, '的任务');
return;
}
} else {
// 取最新一条已完成任务
task = await prisma.courseGenerationTask.findFirst({
where: { status: 'completed' },
orderBy: { createdAt: 'desc' },
include: { course: { select: { id: true, title: true } } },
});
if (!task) {
console.log('没有已完成的生成任务');
return;
}
}
console.log('=== 任务信息 ===');
console.log('taskId:', task.id);
console.log('courseId:', task.courseId);
console.log('courseTitle:', task.course?.title ?? '');
console.log('');
const outline = task.outline;
if (!outline || !outline.chapters || !Array.isArray(outline.chapters)) {
console.log('任务无 outline 或 chapters');
return;
}
// 取第一个小节对应的 suggestedContent调用记录里显示的那类内容
let firstSuggestedContent = null;
let firstNodeTitle = '';
for (const ch of outline.chapters) {
if (ch.nodes && Array.isArray(ch.nodes)) {
for (const node of ch.nodes) {
if (node.suggestedContent) {
firstSuggestedContent = node.suggestedContent;
firstNodeTitle = node.title || '';
break;
}
}
if (firstSuggestedContent) break;
}
}
if (!firstSuggestedContent) {
console.log('outline 中未找到 suggestedContent');
} else {
console.log('=== outline 中第一个小节的 suggestedContent调用记录里看到的内容===');
console.log('小节标题:', firstNodeTitle);
console.log('长度:', firstSuggestedContent.length);
const idx = firstSuggestedContent.indexOf('\n');
console.log('第一个 \\n 位置:', idx === -1 ? '无' : idx);
const doubleNewlineCount = (firstSuggestedContent.match(/\n\s*\n/g) || []).length;
console.log('双换行 \\n\\n 出现次数:', doubleNewlineCount);
const splitByDouble = firstSuggestedContent.split(/\n\s*\n/).map((p) => p.trim()).filter((p) => p.length > 0);
console.log('按 /\\n\\s*\\n/ 拆分后段落数:', splitByDouble.length);
console.log('前 350 字符repr:', JSON.stringify(firstSuggestedContent.slice(0, 350)));
console.log('');
}
// 该课程下第一个节点的 node_slides 的 content.paragraphs
const firstNode = await prisma.courseNode.findFirst({
where: { courseId: task.courseId },
orderBy: { orderIndex: 'asc' },
include: { slides: { orderBy: { orderIndex: 'asc' }, take: 1 } },
});
if (!firstNode || !firstNode.slides || firstNode.slides.length === 0) {
console.log('该课程下没有节点或没有 node_slides');
return;
}
const slide = firstNode.slides[0];
const content = slide.content;
console.log('=== 该课程第一个节点的 node_slides.content实际落库===');
console.log('节点标题:', firstNode.title);
console.log('slide id:', slide.id);
if (content && typeof content === 'object' && Array.isArray(content.paragraphs)) {
console.log('paragraphs 数量:', content.paragraphs.length);
content.paragraphs.forEach((p, i) => {
console.log(` [${i}] 长度: ${p.length}, 前80字: ${JSON.stringify(p.slice(0, 80))}`);
});
} else {
console.log('content 或 content.paragraphs 不存在:', content ? Object.keys(content) : 'null');
}
}
main()
.then(() => process.exit(0))
.catch((e) => {
console.error(e);
process.exit(1);
})
.finally(() => prisma.$disconnect());