You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从文件系统生成带嵌套子页面的Page对象列表?

实现嵌套子页面对象的目录解析方案

文件结构

pages/
- Home.jsx
- Blog.jsx
- Post.Blog.jsx
- Posts.Blog.jsx
- private/
-- Admin.jsx
-- Dashboard.jsx
-- admin/
--- Main.Admin.jsx
-- author/
--- Post.Admin.jsx
-- editor/
--- Editor.Admin.jsx

生成规则

  • 扩展名前为单一名称的文件,生成基础页面对象:
    {name:"Home", isPrivate:false, permission:"guest"} 
    
  • 私有目录外的点分隔文件名,生成带subpages的父页面对象,子页面挂载到对应父对象的subpages数组:
    {name:"Blog", isPrivate:false, permission:"guest", subpages:[{name:"Post", isPrivate:false, permission:"guest"},{name:"Posts", isPrivate:false, permission:"guest"}]}
    
  • 私有目录内的文件,isPrivate设为true,permission为所在子目录名,同时生成带subpages的父页面对象:
    {name:"Admin", isPrivate:true, permission:"private", subpages:[{name:"Post",isPrivate:true, permission:"author"},{name:"Main", isPrivate:true, permission:"admin"}]}
    

当前问题代码

之前尝试用循环添加子页面时,递归处理私有目录出现异常,简化后的代码如下:

const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)
const directoryPath = join(__dirname,'../../../../ui/src/pages')
const files = []
const createList = (dir)=>{
    const fileMatrix = fs.readdirSync(dir)
    fileMatrix.map(file=>{
        const filePath = join(dir,file)
        const stats = fs.statSync(filePath) 
        const isDir = stats.isDirectory()
        const isPrivate = filePath.includes('private')
        const permission = isPrivate ? path.dirname(filePath).split('/').pop():"guest"
        const fileParts = path.basename(filePath,'.jsx').split('.')
        const fileName = fileParts[0]
        const parent = fileParts[1]
        if (!isDir){
            file = {
                name:fileName,
                isPrivate,
                permission
            }
            console.log(file)
        }
        else if(isDir){
            createList(filePath)
        }
    })
}

createList(directoryPath);

解决方案代码

核心思路是用映射表跟踪父页面,递归遍历目录时自动挂载子页面,同时正确处理私有目录的权限逻辑:

const fs = require('fs');
const path = require('path');
const { fileURLToPath } = require('url');

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const directoryPath = path.join(__dirname, '../../../../ui/src/pages');

// 映射表:快速查找已创建的页面对象,避免重复创建
const pageMap = new Map();
// 最终输出的页面对象列表
const pageList = [];

const createPageList = (dir) => {
    const items = fs.readdirSync(dir);
    
    items.forEach(item => {
        const itemPath = path.join(dir, item);
        const stats = fs.statSync(itemPath);
        const isDir = stats.isDirectory();
        const isPrivate = itemPath.includes('private');
        
        if (isDir) {
            // 递归处理子目录
            createPageList(itemPath);
            return;
        }
        
        // 解析文件名和父页面名称
        const baseName = path.basename(itemPath, '.jsx');
        const [pageName, parentPageName] = baseName.split('.');
        
        // 确定权限值
        let permission = 'guest';
        if (isPrivate) {
            const relativePath = path.relative(directoryPath, itemPath);
            const pathSegments = relativePath.split(path.sep);
            const privateIndex = pathSegments.indexOf('private');
            // 取private目录下的直接子目录作为权限,没有则设为private
            permission = privateIndex !== -1 && pathSegments.length > privateIndex + 1 
                ? pathSegments[privateIndex + 1] 
                : 'private';
        }
        
        const pageObj = {
            name: pageName,
            isPrivate,
            permission,
            subpages: []
        };
        
        if (!parentPageName) {
            // 无父页面,直接加入列表(去重)
            if (!pageMap.has(pageName)) {
                pageMap.set(pageName, pageObj);
                pageList.push(pageObj);
            }
        } else {
            // 有父页面,先查找或创建父页面对象
            let parentPage = pageMap.get(parentPageName);
            if (!parentPage) {
                parentPage = {
                    name: parentPageName,
                    isPrivate: isPrivate,
                    permission: isPrivate ? 'private' : 'guest',
                    subpages: []
                };
                pageMap.set(parentPageName, parentPage);
                pageList.push(parentPage);
            }
            // 将当前页面对象加入父页面的subpages数组
            parentPage.subpages.push(pageObj);
        }
    });
};

createPageList(directoryPath);
console.log(JSON.stringify(pageList, null, 2));

代码说明

  • pageMap映射表:解决父页面重复创建的问题,同时提供O(1)的查找效率,方便快速挂载子页面。
  • 递归目录处理:遍历所有层级的文件和目录,确保私有目录下的文件也能被正确解析。
  • 权限逻辑优化:通过相对路径解析private目录的位置,准确获取文件所在的子目录作为权限值。
  • 子页面挂载:自动处理父页面不存在的情况,先创建父页面基础结构,再将子页面加入其subpages数组。

内容的提问来源于stack exchange,提问作者Nineisten

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 04:32:20