98 lines
3.2 KiB
JavaScript
98 lines
3.2 KiB
JavaScript
|
|
#!/usr/bin/env node
|
|||
|
|
/**
|
|||
|
|
* 查看最近 3 条已完成课程的 outline 与正文样本,检查单引号 '' 出现位置
|
|||
|
|
* 用法:node scripts/inspect-quotes-server.js
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
const { PrismaClient } = require('@prisma/client');
|
|||
|
|
const prisma = new PrismaClient();
|
|||
|
|
|
|||
|
|
function hasSingleQuotes(s) {
|
|||
|
|
if (!s || typeof s !== 'string') return false;
|
|||
|
|
const single = ["'", "'", "'", "''", "''", "`"];
|
|||
|
|
return single.some((c) => s.includes(c));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function showQuotes(s, label) {
|
|||
|
|
if (!s) return;
|
|||
|
|
const str = String(s);
|
|||
|
|
if (!hasSingleQuotes(str)) return;
|
|||
|
|
const idx = str.search(/[''`]/);
|
|||
|
|
if (idx === -1) return;
|
|||
|
|
const slice = str.slice(Math.max(0, idx - 20), idx + 30);
|
|||
|
|
console.log(` [单引号] ${label}: ...${slice}...`);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async function main() {
|
|||
|
|
const tasks = await prisma.courseGenerationTask.findMany({
|
|||
|
|
where: { status: 'completed' },
|
|||
|
|
orderBy: { createdAt: 'desc' },
|
|||
|
|
take: 3,
|
|||
|
|
include: { course: { select: { id: true, title: true } } },
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
if (tasks.length === 0) {
|
|||
|
|
console.log('没有已完成的课程');
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
console.log('=== 最近 3 条已完成课程:单引号检查 ===\n');
|
|||
|
|
|
|||
|
|
for (let t = 0; t < tasks.length; t++) {
|
|||
|
|
const task = tasks[t];
|
|||
|
|
const outline = task.outline;
|
|||
|
|
console.log(`--- 课程 ${t + 1}: ${task.course?.title ?? task.courseId} ---`);
|
|||
|
|
console.log('courseId:', task.courseId);
|
|||
|
|
console.log('createdAt:', task.createdAt?.toISOString?.() ?? task.createdAt);
|
|||
|
|
|
|||
|
|
if (outline && outline.chapters && Array.isArray(outline.chapters)) {
|
|||
|
|
for (let c = 0; c < outline.chapters.length; c++) {
|
|||
|
|
const ch = outline.chapters[c];
|
|||
|
|
const parentTitle = ch.parent_title ?? ch.title ?? '';
|
|||
|
|
if (hasSingleQuotes(parentTitle)) {
|
|||
|
|
console.log(` 章节标题含单引号: "${parentTitle}"`);
|
|||
|
|
showQuotes(parentTitle, '章节');
|
|||
|
|
}
|
|||
|
|
if (ch.nodes && Array.isArray(ch.nodes)) {
|
|||
|
|
for (let n = 0; n < ch.nodes.length; n++) {
|
|||
|
|
const node = ch.nodes[n];
|
|||
|
|
const nodeTitle = node.title ?? '';
|
|||
|
|
if (hasSingleQuotes(nodeTitle)) {
|
|||
|
|
console.log(` 节点标题含单引号: "${nodeTitle}"`);
|
|||
|
|
showQuotes(nodeTitle, '节点');
|
|||
|
|
}
|
|||
|
|
const content = node.suggestedContent ?? '';
|
|||
|
|
if (hasSingleQuotes(content)) {
|
|||
|
|
showQuotes(content, '正文');
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
// 只打印第一个小节的正文前 400 字,便于看单引号
|
|||
|
|
let firstContent = null;
|
|||
|
|
for (const ch of outline.chapters) {
|
|||
|
|
if (ch.nodes && ch.nodes[0] && ch.nodes[0].suggestedContent) {
|
|||
|
|
firstContent = ch.nodes[0].suggestedContent;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if (firstContent && hasSingleQuotes(firstContent)) {
|
|||
|
|
console.log(' 首段正文中含单引号,片段:');
|
|||
|
|
const singleIdx = firstContent.search(/[''`]/);
|
|||
|
|
if (singleIdx !== -1) {
|
|||
|
|
console.log(' ', firstContent.slice(Math.max(0, singleIdx - 25), singleIdx + 40));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
console.log('');
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
main()
|
|||
|
|
.then(() => process.exit(0))
|
|||
|
|
.catch((e) => {
|
|||
|
|
console.error(e);
|
|||
|
|
process.exit(1);
|
|||
|
|
})
|
|||
|
|
.finally(() => prisma.$disconnect());
|