| 698 | |
| 699 | // 读取目录结构 - 支持所有文件 |
| 700 | function readDirectoryTree(dirPath, basePath = '', maxDepth = null, currentDepth = 0) { |
| 701 | const items = [] |
| 702 | |
| 703 | // 先检查目录是否存在 |
| 704 | if (!fs.existsSync(dirPath)) { |
| 705 | return items |
| 706 | } |
| 707 | |
| 708 | try { |
| 709 | const entries = fs.readdirSync(dirPath, { withFileTypes: true }) |
| 710 | .filter((entry) => { |
| 711 | if (entry.isDirectory() && (entry.name === 'node_modules' || entry.name === '.git')) return false |
| 712 | return true |
| 713 | }) |
| 714 | .sort((a, b) => { |
| 715 | const aIsDir = a.isDirectory() |
| 716 | const bIsDir = b.isDirectory() |
| 717 | if (aIsDir !== bIsDir) return aIsDir ? -1 : 1 |
| 718 | return fileNameCollator.compare(a.name, b.name) |
| 719 | }) |
| 720 | |
| 721 | for (const entry of entries) { |
| 722 | |
| 723 | const fullPath = path.join(dirPath, entry.name) |
| 724 | const relativePath = basePath ? path.join(basePath, entry.name) : entry.name |
| 725 | |
| 726 | if (entry.isDirectory()) { |
| 727 | const nextDepth = currentDepth + 1 |
| 728 | const canDescend = maxDepth === null || nextDepth <= maxDepth |
| 729 | const children = canDescend |
| 730 | ? readDirectoryTree(fullPath, relativePath, maxDepth, nextDepth) |
| 731 | : [] |
| 732 | items.push({ |
| 733 | id: relativePath, |
| 734 | name: entry.name, |
| 735 | type: 'folder', |
| 736 | path: relativePath, |
| 737 | children, |
| 738 | childrenLoaded: canDescend, |
| 739 | isExpanded: false |
| 740 | }) |
| 741 | } else { |
| 742 | // 支持所有文件类型 |
| 743 | items.push({ |
| 744 | id: relativePath, |
| 745 | name: entry.name, |
| 746 | type: 'file', |
| 747 | path: relativePath, |
| 748 | fileType: getFileType(entry.name) |
| 749 | }) |
| 750 | } |
| 751 | } |
| 752 | } catch (err) { |
| 753 | // 静默处理目录不存在错误 |
| 754 | if (err.code !== 'ENOENT') { |
| 755 | console.error('读取目录失败:', err.message) |
| 756 | } |
| 757 | } |