/** * 在有用户笔记的节点插入系统笔记 * 插入10条系统笔记到有用户笔记的节点 */ import prisma from '../src/utils/prisma'; import { SYSTEM_USER_ID } from '../src/constants'; import { logger } from '../src/utils/logger'; /** * 确保系统用户存在 */ async function ensureSystemUser() { const existingUser = await prisma.user.findUnique({ where: { id: SYSTEM_USER_ID }, }); if (existingUser) { logger.info('系统用户已存在'); return existingUser; } const systemUser = await prisma.user.create({ data: { id: SYSTEM_USER_ID, nickname: '系统', agreementAccepted: true, }, }); logger.info('系统用户创建成功'); return systemUser; } /** * 查找有用户笔记的节点 */ async function findNodesWithUserNotes() { // 查找有用户笔记的节点(排除系统笔记) const notesWithNodes = await prisma.note.findMany({ where: { nodeId: { not: null }, userId: { not: SYSTEM_USER_ID }, // 只统计用户笔记 }, select: { nodeId: true, }, distinct: ['nodeId'], take: 10, // 取前10个节点 }); const nodeIds = notesWithNodes .map((item) => item.nodeId) .filter((id): id is string => id !== null); logger.info(`找到 ${nodeIds.length} 个有用户笔记的节点`); if (nodeIds.length === 0) { // 如果没有用户笔记,使用"高效沟通的艺术"课程的前两节 logger.info('没有找到用户笔记,使用"高效沟通的艺术"课程的前两节'); const courseId = 'course_vertical_001'; const node1Id = 'node_vertical_001_01'; const node2Id = 'node_vertical_001_02'; const nodes = await prisma.courseNode.findMany({ where: { id: { in: [node1Id, node2Id] }, }, include: { course: { select: { id: true, title: true, }, }, }, }); return nodes; } // 获取节点详情 const nodes = await prisma.courseNode.findMany({ where: { id: { in: nodeIds }, }, include: { course: { select: { id: true, title: true, }, }, }, }); return nodes; } /** * 创建系统笔记 */ async function createSystemNote(data: { nodeId: string; courseId: string; startIndex: number; length: number; type: 'highlight' | 'thought'; content?: string; quotedText: string; }) { // 检查是否已存在相同的系统笔记(避免重复创建) const existing = await prisma.note.findFirst({ where: { userId: SYSTEM_USER_ID, nodeId: data.nodeId, startIndex: data.startIndex, length: data.length, type: data.type, }, }); if (existing) { logger.info(`系统笔记已存在: ${data.quotedText.substring(0, 20)}...`); return existing; } const note = await prisma.note.create({ data: { userId: SYSTEM_USER_ID, courseId: data.courseId, nodeId: data.nodeId, startIndex: data.startIndex, length: data.length, type: data.type, content: data.content || '', quotedText: data.quotedText, }, }); logger.info(`系统笔记创建成功: ${data.quotedText.substring(0, 20)}...`); return note; } /** * 主函数 */ async function main() { try { logger.info('开始在有用户笔记的节点插入系统笔记...'); // 1. 确保系统用户存在 await ensureSystemUser(); // 2. 查找有用户笔记的节点 const nodes = await findNodesWithUserNotes(); if (nodes.length === 0) { logger.info('没有找到有用户笔记的节点'); return; } // 3. 为每个节点创建系统笔记 let createdCount = 0; const targetCount = 10; for (const node of nodes) { if (createdCount >= targetCount) { break; } logger.info(`为节点 "${node.title}" 创建系统笔记...`); // 获取该节点的用户笔记,用于生成系统笔记的位置 const userNotes = await prisma.note.findMany({ where: { nodeId: node.id, userId: { not: SYSTEM_USER_ID }, }, orderBy: { createdAt: 'asc' }, take: 5, // 每个节点最多创建5条系统笔记 }); logger.info(`节点 "${node.title}" 有 ${userNotes.length} 条用户笔记`); // 获取该节点的现有系统笔记,用于创建重叠的笔记 const existingSystemNotes = await prisma.note.findMany({ where: { nodeId: node.id, userId: SYSTEM_USER_ID, }, orderBy: { createdAt: 'asc' }, take: 10, }); logger.info(`节点 "${node.title}" 现有 ${existingSystemNotes.length} 条系统笔记`); // 为现有系统笔记创建重叠的笔记(如果有有效的startIndex) for (const existingNote of existingSystemNotes) { if (createdCount >= targetCount) { break; } if (existingNote.startIndex === null || existingNote.length === null) { continue; // 跳过无效的笔记 } // 如果 startIndex 是 0,说明是测试数据,跳过 if (existingNote.startIndex === 0) { continue; } // 创建与现有系统笔记部分重叠的新系统笔记 const overlapStart = existingNote.startIndex + Math.floor(existingNote.length / 2); const systemNoteLength = Math.max(15, existingNote.length); const systemNoteQuotedText = existingNote.quotedText ? `${existingNote.quotedText.substring(Math.floor(existingNote.quotedText.length / 2))}(系统补充)` : '系统笔记内容(重叠测试)'; const type = existingNote.type === 'highlight' ? 'thought' : 'highlight'; const content = type === 'thought' ? '这是一个系统笔记,用于测试重叠显示逻辑。当与用户笔记重叠时,只显示用户笔记的线段。' : undefined; await createSystemNote({ nodeId: node.id, courseId: node.courseId, startIndex: overlapStart, length: systemNoteLength, type, content, quotedText: systemNoteQuotedText, }); createdCount++; } // 如果有用户笔记,为每个用户笔记创建系统笔记(部分重叠,部分不重叠) if (userNotes.length > 0) { // 有用户笔记的情况:为每个用户笔记创建系统笔记(部分重叠,部分不重叠) for (let i = 0; i < userNotes.length && createdCount < targetCount; i++) { const userNote = userNotes[i]; if (!userNote.startIndex || !userNote.length) { continue; } // 策略1:创建与用户笔记部分重叠的系统笔记(用于测试重叠逻辑) if (i % 2 === 0 && createdCount < targetCount) { // 重叠情况:系统笔记从用户笔记中间开始,延伸到后面 const overlapStart = userNote.startIndex + Math.floor(userNote.length / 2); const systemNoteLength = Math.max(15, userNote.length); const systemNoteQuotedText = userNote.quotedText ? `${userNote.quotedText.substring(Math.floor(userNote.quotedText.length / 2))}(系统补充)` : '系统笔记内容(重叠测试)'; const type = 'highlight'; await createSystemNote({ nodeId: node.id, courseId: node.courseId, startIndex: overlapStart, length: systemNoteLength, type, quotedText: systemNoteQuotedText, }); createdCount++; } // 策略2:创建不重叠的系统笔记(在用户笔记前面或后面) if (createdCount < targetCount) { // 在用户笔记前面创建系统笔记 const beforeStartIndex = Math.max(0, userNote.startIndex - 30); const beforeLength = Math.min(20, userNote.startIndex - beforeStartIndex); if (beforeLength > 5) { const systemNoteQuotedText = '系统笔记:这是不重叠的部分'; const type = Math.random() > 0.5 ? 'thought' : 'highlight'; const content = type === 'thought' ? '这是一个系统笔记,用于测试非重叠显示逻辑。' : undefined; await createSystemNote({ nodeId: node.id, courseId: node.courseId, startIndex: beforeStartIndex, length: beforeLength, type, content, quotedText: systemNoteQuotedText, }); createdCount++; } } } } // ✅ 如果还不够10条,直接创建系统笔记(不依赖现有笔记) const notesPerNode = Math.ceil(targetCount / nodes.length); const remainingCount = Math.min(notesPerNode, targetCount - createdCount); for (let i = 0; i < remainingCount && createdCount < targetCount; i++) { const startIndex = 100 + i * 50; // 每个笔记间隔50个字符,从100开始 const length = 20; const systemNoteQuotedText = `系统笔记 ${createdCount + 1}:这是不重叠的部分`; const type = createdCount % 2 === 0 ? 'thought' : 'highlight'; const content = type === 'thought' ? `系统想法笔记 ${createdCount + 1}:这是一个系统笔记,用于测试非重叠显示逻辑。` : undefined; await createSystemNote({ nodeId: node.id, courseId: node.courseId, startIndex, length, type, content, quotedText: systemNoteQuotedText, }); createdCount++; } } logger.info(`系统笔记创建完成!共创建 ${createdCount} 条系统笔记`); } catch (error) { logger.error('创建系统笔记失败:', error); throw error; } finally { await prisma.$disconnect(); } } // 运行脚本 main() .then(() => { process.exit(0); }) .catch((error) => { console.error(error); process.exit(1); });