React与Prisma ORM实现嵌套列表:子索引创建及文件上传需求
实现层级索引与文件上传的方案
核心思路
先定义清晰的索引节点数据结构,通过迭代法构建层级关系(替代递归),再为每个节点绑定文件上传逻辑,最终映射到实际的文件夹层级。
1. 定义索引节点结构
不管用什么语言,每个索引节点需要包含这些核心字段:
// JavaScript示例,其他语言可类比 const indexNode = { id: '1.1', // 索引编号,如1.1、1.2.1 title: 'subtitle01',// 索引标题 parentId: '1', // 父节点ID,根节点为空 files: [], // 存储该节点下的文件信息 children: [] // 子节点列表 };
2. 迭代法构建层级索引树
递归在层级过深时容易触发栈溢出,迭代法更稳定可控:
function buildIndexTree(nodes) { const nodeMap = new Map(); const rootNodes = []; // 第一步:将所有节点存入Map,快速查找 nodes.forEach(node => { nodeMap.set(node.id, { ...node, children: [], files: [] }); }); // 第二步:迭代关联父子节点 nodes.forEach(node => { if (node.parentId) { const parentNode = nodeMap.get(node.parentId); parentNode?.children.push(nodeMap.get(node.id)); } else { rootNodes.push(nodeMap.get(node.id)); } }); return rootNodes; }
3. 给指定索引节点上传文件
根据节点ID找到目标节点,添加文件信息并生成对应路径:
function uploadFileToIndex(nodeId, file, nodeMap) { const targetNode = nodeMap.get(nodeId); if (!targetNode) return; // 生成文件对应的文件夹路径(把索引的.替换成/) const filePath = `${targetNode.id.replace(/\./g, '/')}/${file.name}`; targetNode.files.push({ name: file.name, tempPath: file.tempFilePath, // 上传文件的临时存储路径 finalPath: filePath }); // 这里可添加实际文件存储逻辑:比如从tempPath复制到finalPath对应的磁盘位置 }
4. 生成实际的文件夹层级
用迭代栈处理所有节点,创建对应文件夹并存储文件(Node.js示例):
const fs = require('fs').promises; const path = require('path'); async function createFolderStructure(rootNodes, rootDir) { for (const root of rootNodes) { // 创建根节点文件夹 const rootFolder = path.join(rootDir, root.id.replace(/\./g, '/')); await fs.mkdir(rootFolder, { recursive: true }); // 存储根节点下的文件 for (const file of root.files) { await fs.copyFile(file.tempPath, path.join(rootFolder, file.name)); } // 用栈迭代处理所有子节点 const stack = [...root.children]; while (stack.length > 0) { const child = stack.pop(); const childFolder = path.join(rootDir, child.id.replace(/\./g, '/')); await fs.mkdir(childFolder, { recursive: true }); // 存储子节点下的文件 for (const file of child.files) { await fs.copyFile(file.tempPath, path.join(childFolder, file.name)); } // 将子节点的子节点推入栈,继续处理 stack.push(...child.children); } } }
递归方案的优化(如果坚持用递归)
如果一定要用递归,可通过尾递归优化(部分语言如JavaScript、Python支持)或限制递归深度避免栈溢出:
// 尾递归版本的层级构建 function buildTreeTailRecursive(nodes, nodeMap = new Map(), rootNodes = [], index = 0) { if (index >= nodes.length) return rootNodes; const node = nodes[index]; const currentNode = { ...node, children: [], files: [] }; nodeMap.set(node.id, currentNode); if (node.parentId) { nodeMap.get(node.parentId)?.children.push(currentNode); } else { rootNodes.push(currentNode); } return buildTreeTailRecursive(nodes, nodeMap, rootNodes, index + 1); }
内容的提问来源于stack exchange,提问作者Jim Ft Dev
相关产品推荐
相关产品推荐

