release: v1.0.0

This commit is contained in:
2026-05-16 17:34:32 +08:00
commit 2f521deff8
15 changed files with 4718 additions and 0 deletions

View File

@@ -0,0 +1,445 @@
# 目录树生成脚本 — 技术方案设计Windows 平台)
> 任务 ID: T023 | 项目 ID: PROJ-20260509011
> 功能清单: F013-F0208 个功能,全部审批通过)
> 运行平台: Windows
> 设计日期: 2026-05-16
> 设计者: 脚本架构师
---
## 1. 技术选型评估
### 1.1 功能级可行性分析BAT vs Python
| 功能编号 | 功能名称 | BAT 可行性 | Python 可行性 | 关键问题 |
|---------|---------|-----------|--------------|---------|
| F013 | 接收路径输入 | ✅ 完全可行 | ✅ 完全可行 | BAT: `%~1` 即可Python: `argparse` |
| F014 | 加载忽略配置 | ⚠️ 勉强可行 | ✅ 完全可行 | BAT 读取配置文件需逐行 `for /f`,无结构化解析能力 |
| F015 | 递归遍历目录 | ⚠️ 勉强可行 | ✅ 完全可行 | BAT `for /r` 可递归但无法灵活控制跳过逻辑 |
| F016 | 生成目录树(├── 字符) | ❌ **不可行** | ✅ 完全可行 | Windows CMD 默认代码页 936 (GBK) 无法正确显示 `├` `─` 等 Unicode 制表符;需 `chcp 65001` 且仍有渲染问题。BAT 字符串拼接缩进极其困难 |
| F017 | 生成文件树 | ⚠️ 勉强可行 | ✅ 完全可行 | BAT `dir /s/b` 可列出文件,但格式化输出困难 |
| F018 | 终端输出 | ⚠️ 有条件可行 | ✅ 完全可行 | BAT 需处理 `chcp 65001` 编码切换,输出重定向时易乱码 |
| F019 | Markdown 保存 | ⚠️ 勉强可行 | ✅ 完全可行 | BAT 可 `echo > file.md`,但 Markdown 结构化内容拼接繁琐 |
| F020 | 统计信息(目录数/文件数/总大小) | ❌ **困难** | ✅ 完全可行 | BAT 无原生文件大小累加能力,`%%~zI``for` 循环中可用但累加大文件时易溢出BAT 整数仅支持 32 位) |
### 1.2 BAT 核心缺陷总结
1. **Unicode 制表符渲染**F016 要求输出 `├──` `└──` `│` 等字符Windows CMD 默认代码页下这些字符会显示为乱码。虽然 `chcp 65001` 可以切换 UTF-8但在 Windows 10 之前的系统上存在严重兼容性问题,且输出重定向到文件时编码转换不可靠。
2. **字符串处理**BAT 的字符串拼接、缩进管理极其笨拙,无法优雅实现树形缩进逻辑。
3. **大文件统计**BAT 的整数运算限制在 32 位有符号范围(约 ±21 亿),总大小超过 2GB 时会溢出。
4. **错误处理**BAT 缺乏结构化异常处理机制try/catch错误恢复困难。
5. **配置解析**BAT 无法优雅解析结构化配置文件JSON/INI只能逐行文本处理。
### 1.3 评估结论
**BAT 无法胜任 F016目录树 Unicode 渲染)和 F020大文件统计其余功能也均存在明显缺陷。**
---
## 2. 技术选型结论
### 最终选择Python 3.8+(标准库,无第三方依赖)
**理由:**
| 维度 | 说明 |
|-----|------|
| 功能覆盖 | 8 个功能全部可完美实现,无妥协 |
| Unicode 支持 | Python 原生 UTF-8 支持,`├──` 等字符渲染无问题 |
| 标准库 | `pathlib``os``argparse``datetime` 覆盖所有需求 |
| 文件大小 | Python 整数自动扩展,无溢出问题 |
| 跨版本兼容 | Python 3.8+ 覆盖 Windows 7 SP1 及以上所有版本 |
| 可维护性 | 代码结构清晰,模块化设计,易于扩展 |
| 部署 | 单文件 `.py`,用户只需安装 PythonWindows 10/11 可通过 Microsoft Store 一键安装) |
---
## 3. 项目结构
```
tree_generator/
├── tree_gen.py # 主程序(单文件,包含所有模块)
├── .treeignore # 忽略配置文件(可选,放在目标目录下)
├── tree_output.md # 默认输出文件(运行后生成)
└── README.md # 使用文档(由 Web 文档生成 Agent 创建)
```
**设计原则:**
- 主程序 `tree_gen.py` 为单文件,不拆分为多模块,便于分发和使用
- 忽略配置文件 `.treeignore` 放在目标目录下,遵循 `.gitignore` 惯例
- 输出文件默认在当前工作目录生成
---
## 4. 模块说明表
| 模块名 | 负责功能 | 输入 | 输出 | 依赖 |
|-------|---------|------|------|------|
| `ArgParser` | F013 路径输入 | 命令行参数 `sys.argv` | 解析后的配置对象(目标路径、输出路径、深度限制等) | `argparse` 标准库 |
| `IgnoreLoader` | F014 忽略配置 | 配置文件路径(`.treeignore` | 忽略目录名称集合 `set[str]` | `pathlib` 标准库 |
| `DirectoryScanner` | F015 递归遍历 | 目标路径 + 忽略集合 | 目录树结构(嵌套字典) | `pathlib``os` 标准库 |
| `TreeFormatter` | F016 目录树 + F017 文件树 | 目录树结构 | 格式化字符串(含 `├──` 缩进) | 无额外依赖 |
| `TerminalOutput` | F018 终端输出 | 格式化字符串 | 终端显示stdout | `sys` 标准库(编码设置) |
| `MarkdownWriter` | F019 Markdown 保存 | 格式化字符串 + 输出路径 | `.md` 文件 | `pathlib` 标准库 |
| `StatisticsCollector` | F020 统计信息 | 目录树结构 | 统计信息字典(目录数、文件数、总大小) | `os` 标准库 |
---
## 5. 技术选型结论总结
```
┌─────────────────────────────────────────────────────┐
│ 最终技术选型Python 3.8+ 标准库 │
│ │
│ 核心文件tree_gen.py单文件约 300-400 行) │
│ 配置文件:.treeignore可选
│ 输出文件tree_output.md默认
│ │
│ 选择理由: │
│ 1. BAT 无法正确处理 Unicode 制表符F016
│ 2. BAT 整数溢出问题F020 大文件统计) │
│ 3. Python 标准库完全覆盖所有 8 个功能 │
│ 4. 单文件部署,零第三方依赖 │
└─────────────────────────────────────────────────────┘
```
---
## 6. 错误处理策略
### 6.1 异常分类与处理
| 异常类型 | 触发条件 | 处理策略 | 用户提示 |
|---------|---------|---------|---------|
| `PathNotFoundError` | 目标路径不存在 | 捕获 `FileNotFoundError`,退出并提示 | `错误: 路径 "xxx" 不存在,请检查输入` |
| `PermissionError` | 无权限访问目录 | 跳过该目录,记录警告,继续遍历 | `警告: 无权限访问 "xxx",已跳过` |
| `SymlinkLoopError` | 符号链接循环 | 使用 `pathlib.Path.resolve()` 检测,跳过已访问路径 | `警告: 检测到符号链接循环,已跳过` |
| `EncodingError` | 文件名含特殊字符 | 使用 `errors='replace'` 容错 | 静默替换,不中断 |
| `OutputWriteError` | 无法写入输出文件 | 捕获 `IOError`/`PermissionError`,回退到仅终端输出 | `警告: 无法写入文件,仅显示到终端` |
| `InvalidConfigError` | 忽略配置文件格式错误 | 使用默认忽略列表,记录警告 | `警告: 配置文件格式错误,使用默认配置` |
### 6.2 退出码规范
| 退出码 | 含义 |
|-------|------|
| 0 | 成功完成 |
| 1 | 参数错误(路径不存在、格式错误) |
| 2 | 运行时错误(写入失败等) |
| 3 | 中断Ctrl+C |
---
## 7. 接口定义
### 7.1 数据流图
```
┌──────────┐ ┌──────────────┐ ┌─────────────────┐
│ 命令行参数 │────▶│ ArgParser │────▶│ Config 对象 │
│ sys.argv │ │ (F013) │ │ {path, output, │
└──────────┘ └──────────────┘ │ ignore, depth} │
└────────┬────────┘
┌───────────────────────────┼───────────────────────────┐
│ │ │
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│IgnoreLoader │ │Directory │ │Statistics │
│(F014) │ │Scanner │ │Collector │
│ │ │(F015) │ │(F020) │
│.treeignore │ │ │ │ │
└──────┬───────┘ └──────┬───────┘ └──────┬───────┘
│ │ │
▼ ▼ │
ignore_set tree_dict │
(set[str]) (嵌套字典) │
│ │
▼ │
┌──────────────────┐ │
│ TreeFormatter │◀────────────────────┘
│ (F016/F017) │
│ │
│ tree_str │
│ file_list_str │
└────────┬────────┘
┌───────────────────┼───────────────────┐
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Terminal │ │ Markdown │ │ 统计信息 │
│ Output │ │ Writer │ │ 输出 │
│ (F018) │ │ (F019) │ │ │
│ │ │ │ │ │
│ stdout │ │ tree_output │ │ 目录/文件/ │
│ │ │ .md │ │ 总大小 │
└──────────────┘ └──────────────┘ └──────────────┘
```
### 7.2 核心数据结构
```python
# Config 对象ArgParser 输出)
Config = {
"target_path": Path, # 目标目录路径
"output_path": Path, # Markdown 输出路径(默认 tree_output.md
"ignore_dirs": set[str], # 忽略目录名称集合
"max_depth": int | None, # 最大递归深度None = 无限制)
"files_only": bool, # 仅显示文件模式
"dirs_only": bool, # 仅显示目录模式
}
# 目录树结构DirectoryScanner 输出)
TreeDict = {
"name": str, # 目录/文件名
"path": Path, # 完整路径
"is_dir": bool, # 是否为目录
"children": list[TreeDict], # 子节点列表(目录时有效)
"size": int, # 文件大小(文件时有效)
}
# 统计信息StatisticsCollector 输出)
Statistics = {
"dir_count": int, # 目录数量
"file_count": int, # 文件数量
"total_size": int, # 总大小(字节)
"total_size_human": str, # 人类可读大小(如 "1.23 GB"
}
```
### 7.3 模块间接口
| 调用方 | 被调用方 | 接口方法 | 参数 | 返回值 |
|-------|---------|---------|------|--------|
| `main()` | `ArgParser` | `parse_args()` | `sys.argv[1:]` | `Config` |
| `main()` | `IgnoreLoader` | `load_ignores(config)` | `Config` | `set[str]` |
| `main()` | `DirectoryScanner` | `scan(path, ignore_set, max_depth)` | `Path, set[str], int\|None` | `TreeDict` |
| `main()` | `TreeFormatter` | `format_tree(tree, style)` | `TreeDict, str` | `str` |
| `main()` | `TreeFormatter` | `format_files(tree)` | `TreeDict` | `str` |
| `main()` | `TerminalOutput` | `output(text)` | `str` | `None` |
| `main()` | `MarkdownWriter` | `write(text, path)` | `str, Path` | `None` |
| `main()` | `StatisticsCollector` | `collect(tree)` | `TreeDict` | `Statistics` |
---
## 8. 忽略配置方案F014
### 8.1 配置文件格式
文件名:`.treeignore`(放在目标目录下)
```
# 忽略配置示例
# 每行一个目录名,支持 # 注释
.git
.gitignore
node_modules
__pycache__
*.pyc
.DS_Store
Thumbs.db
venv
.env
.idea
.vscode
dist
build
*.egg-info
```
### 8.2 内置默认忽略列表
`.treeignore` 不存在时,使用以下默认列表:
```python
DEFAULT_IGNORE = {
".git", ".svn", ".hg", # 版本控制
"node_modules", "bower_components", # Node.js
"__pycache__", "*.pyc", ".pytest_cache", # Python
".idea", ".vscode", # IDE
"dist", "build", "target", # 构建产物
".DS_Store", "Thumbs.db", # 系统文件
"venv", ".venv", "env", # 虚拟环境
}
```
### 8.3 匹配规则
- 目录名精确匹配不区分大小写Windows 特性)
- 支持 `*` 通配符(如 `*.pyc`
- 忽略配置仅作用于目录级别,不递归检查文件内容
---
## 9. 树形输出格式规范F016/F017
### 9.1 目录树格式
```
项目根目录/
├── src/
│ ├── main.py
│ ├── utils/
│ │ ├── helper.py
│ │ └── config.py
│ └── models/
│ └── user.py
├── tests/
│ ├── test_main.py
│ └── test_utils.py
├── config.json
└── README.md
```
**规则:**
- 目录名后加 `/` 后缀
- 分支符:`├── `(有后续兄弟节点)/ `└── `(最后一个节点)
- 缩进线:`│ `(有后续兄弟节点)/ ` `(无后续兄弟节点)
- 缩进单位4 个字符(`│` + 3 空格 或 4 空格)
### 9.2 文件树格式
```
文件列表:
C:\project\src\main.py
C:\project\src\utils\helper.py
C:\project\src\utils\config.py
C:\project\src\models\user.py
C:\project\tests\test_main.py
C:\project\tests\test_utils.py
C:\project\config.json
C:\project\README.md
```
**规则:**
- 每个文件一行,带完整绝对路径
- 使用 Windows 风格路径分隔符 `\`
- 按字母顺序排序
### 9.3 统计信息格式
```
统计信息:
目录数: 5
文件数: 8
总大小: 24.5 KB (25,088 字节)
```
---
## 10. Markdown 保存方案F019
### 10.1 输出文件格式
```markdown
# 目录树 — 项目根目录
> 生成时间: 2026-05-16 16:00:00
> 目标路径: C:\project
> 扫描深度: 无限制
## 目录结构
```
项目根目录/
├── src/
│ ├── main.py
│ └── utils/
│ └── helper.py
├── config.json
└── README.md
```
## 文件列表
| # | 文件路径 |
|---|---------|
| 1 | `C:\project\src\main.py` |
| 2 | `C:\project\src\utils\helper.py` |
| 3 | `C:\project\config.json` |
| 4 | `C:\project\README.md` |
## 统计信息
- **目录数:** 3
- **文件数:** 4
- **总大小:** 1.2 KB (1,234 字节)
```
### 10.2 保存策略
- 默认文件名:`tree_output.md`(当前工作目录)
- 可通过 `-o` / `--output` 参数指定自定义路径
- 文件已存在时覆盖写入(不追加)
- 编码UTF-8 with BOMWindows 记事本兼容)
---
## 11. 命令行接口设计
```
usage: tree_gen.py [-h] [-o OUTPUT] [-d DEPTH] [-f] [-D] [-i IGNORE_FILE] [path]
目录树生成脚本 - Windows 平台
positional arguments:
path 目标目录路径(默认: 当前目录)
options:
-h, --help 显示帮助信息
-o OUTPUT, --output OUTPUT
Markdown 输出文件路径(默认: tree_output.md
-d DEPTH, --depth DEPTH
最大递归深度(默认: 无限制)
-f, --files-only 仅显示文件树
-D, --dirs-only 仅显示目录树
-i IGNORE_FILE, --ignore IGNORE_FILE
忽略配置文件路径(默认: 目标目录下的 .treeignore
```
### 使用示例
```bash
# 扫描当前目录
python tree_gen.py
# 扫描指定目录
python tree_gen.py C:\Users\test\project
# 指定输出文件和深度
python tree_gen.py C:\project -o output.md -d 3
# 仅显示文件
python tree_gen.py C:\project -f
# 自定义忽略配置
python tree_gen.py C:\project -i my_ignore.txt
```
---
## 12. 编码规范
| 项目 | 规范 |
|-----|------|
| 文件编码 | UTF-8Python 源文件) |
| 输出编码 | UTF-8 with BOMMarkdown 文件) |
| 终端编码 | UTF-8通过 `sys.stdout.reconfigure(encoding='utf-8')` 设置) |
| 行尾符 | LFPython 标准) |
| 缩进 | 4 空格 |
| Python 版本 | 3.8+ |
---
## 13. 后续任务
| 任务 | 负责 Agent | 状态 |
|-----|-----------|------|
| T021: Python 代码实现 | BAT 编码 Agent实际应为 Python 编码 Agent | 待激活 |
| T022: 功能测试验证 | 测试验证 Agent | 待激活 |
| T024: 使用文档编写 | Web 文档生成 Agent | 待激活 |
---
*文档结束。等待审批后进入编码阶段。*