import logger from "#logger"; import {chapter_insert, searchChapterInfoForPath, getChaptersByBookId, getFileBymd5} from "#db"; import cliProgress from 'cli-progress'; import {EPub} from "epub2"; import path from "node:path"; import fs from "node:fs"; export async function saveToc(epub, uploadPath, book_id, author_id) { const progressBar = new cliProgress.SingleBar({}, cliProgress.Presets.shades_classic); progressBar.start(epub.toc.length, 0); // 栈用于追踪父章节的 ID const parentStack = []; for (const elm of epub.toc) { try { const match = `${elm.href}`.match(/\/(.*\.html).*/); let chapterInfo = {file_id: ''}; let path = ''; if (match) { path = match[1]; chapterInfo = await searchChapterInfoForPath(path, book_id); } const name = `${elm.title}`; elm.title = ''; // 确定 parent_id let parent_id = null; while (parentStack.length > 0 && parentStack[parentStack.length - 1].level >= elm.level) { parentStack.pop(); } if (parentStack.length > 0) { parent_id = parentStack[parentStack.length - 1].id; } const params = { name: name, book_id: book_id, author_id: author_id, content: JSON.stringify(elm), level: elm.level, order_index: elm.order, order_id: chapterInfo.file_id, old_path: elm.href, path: `./base_files/${book_id}/Text/${chapterInfo.file_id}.html`, parent_id: parent_id, }; logger.info(params); // 插入数据库并获取新插入的章节 ID const insertedId = await chapter_insert(params); // 将当前章节推入栈中 parentStack.push({id: insertedId.insertId, level: elm.level}); } catch (e) { logger.error(e); } finally { progressBar.increment(); } } progressBar.stop(); } function buildTree(data) { const nodeMap = new Map(); const tree = []; // 初始化节点映射 data.forEach(node => { // 确保每个节点都有 children 属性 node.children = []; nodeMap.set(node.id, node); }); // 构建树 data.forEach(node => { if (node.parent_id !== null) { // 确保 id 和 parent_id 类型一致 const parentNode = nodeMap.get(Number(node.parent_id)); if (parentNode) { parentNode.children.push(node); } } else { // 顶层节点 tree.push(node); } }); return tree; } export async function fetchAndBuildTree(book_id) { // 从数据库中获取所有章节数据 const chapters = await getChaptersByBookId(book_id); return buildTree(chapters) } export async function fetchNextFile(fileId, type) { // 从数据库中获取所有章节数据 logger.info(`Found ${fileId}`); const fileRow = await getFileBymd5(fileId); console.log('fileRow', fileRow); console.log('\n') console.log('\n') const epubPath = `./base_files/${fileRow.book_id}/${fileRow.book_id}.epub` if (fs.existsSync(epubPath)) { console.time('chapterIndex') const epubData = fs.readFileSync(epubPath) const epub = await EPub.createAsync(epubData, null, ""); console.log("\nSPINE:\n"); console.log('epubFlowLength', epub.flow.length); // console.log('epubFlowLength', epub.flow[30]); const chapterIndex = epub.flow.findIndex(elm => elm.id === fileRow.source_id); console.log(117, epub.flow[chapterIndex - 1], epub.flow[chapterIndex], epub.flow[chapterIndex + 1]) console.timeEnd('chapterIndex') } }