v1.1.0: 增加交互提示、路径输入、窗口属性配置

- main.py: 增加show_banner()启动说明、各阶段[INFO]日志、结果摘要、任意键退出
- file_selector.py: 重写为路径输入→验证→空输入弹窗回退→不存在循环重试
- run.bat: 新建启动脚本(chcp 65001, mode con cols=80 lines=20, color 0B, title固定署名, pause)
- Code/docs/modification-assessment.md: 修改需求评估文档
This commit is contained in:
2026-05-25 17:29:19 +08:00
parent 5fbc215e59
commit 836ad20515
35 changed files with 4105 additions and 25 deletions

View File

@@ -0,0 +1,471 @@
# PinMAP → PinList 转换器 — 修改需求评估
> **版本**: v1.0
> **日期**: 2026-05-25
> **评估人**: 脚本架构师 (Script Architect)
> **状态**: 待审批
---
## 1. 修改需求总览
| 编号 | 需求 | 优先级 | 复杂度 |
|------|------|--------|--------|
| R1 | 增加交互提示(启动说明、详细日志、结果摘要) | 高 | 低 |
| R2 | 文件选择方式调整(路径输入 → 弹窗回退 → 报错重试) | 高 | 低 |
| R3 | 窗口属性UTF-8 编码、固定窗口、颜色、署名、pause | 高 | 低 |
---
## 2. 逐项需求分析
### 2.1 需求 R1增加交互提示
**现状**
- 当前 `main.py` 启动即进入文件选择,无任何说明
- 日志输出已有 `[INFO]``[WARN]``[ERROR]``[FATAL]` 分级,但粒度不够细
- 转换完成后直接 `return` 退出,窗口瞬间关闭(双击 bat 运行时)
**修改目标**
1. **启动 Banner**:显示程序名称、功能说明、版本信息、署名
2. **详细日志**:在 Excel 读取、PinMAP 解析、验证、生成、写入各阶段增加 `[INFO]` 日志
3. **结果摘要**:转换完成后不立即退出,显示统计摘要,等待用户确认后退出
**具体改动**
```
启动 Banner 示例:
╔══════════════════════════════════════════════════════════╗
║ PinMAP → PinList 转换器 ║
║ 自动将 Excel PinMAP 文件转换为 PinList ║
║ ║
║ 版本: v1.0.1 ║
║ -By: LeeQwQ ║
╚══════════════════════════════════════════════════════════╝
详细日志示例:
[INFO] 正在读取文件: C:\Users\test\sample_4x4.xlsx
[INFO] 文件读取完成,共 16 个非空单元格
[INFO] 正在解析 PinMAP 结构...
[INFO] 解析完成: 4x4 方形,共 12 个Pin
[INFO] 封装信息: QFN-12
[INFO] 正在验证数据...
[INFO] 验证通过0 个错误2 个警告
[INFO] 正在生成 PinList...
[INFO] 正在写入输出文件...
[SUCCESS] 转换完成!
结果摘要示例:
═══════════════════════════════════════════════════════════
转换结果摘要
═══════════════════════════════════════════════════════════
输入文件: C:\Users\test\sample_4x4.xlsx
输出文件: C:\Users\test\sample_4x4_PinList.xlsx
封装信息: QFN-12
Pin 数量: 12
错误数量: 0
警告数量: 2
═══════════════════════════════════════════════════════════
按任意键退出...
```
### 2.2 需求 R2文件选择方式调整
**现状**
- 当前 `file_selector.py``select_file()` 函数:
- 有命令行参数 → 直接使用
- 无命令行参数 → 直接弹出 tkinter 文件对话框
- 无 GUI 环境 → 回退到命令行参数
- **问题**:用户没有"输入路径"的机会,直接跳到了弹窗
**修改目标**
新的文件选择流程:
```
┌─────────────────────────────────────────┐
│ 1. 提示用户输入文件路径 │
│ "请输入 PinMAP 文件路径: " │
├─────────────────────────────────────────┤
│ 2a. 用户输入了路径 │
│ ├─ 路径存在? → 使用该路径 │
│ └─ 路径不存在? → 报错 + 返回步骤 1 │
│ 2b. 用户直接回车(空输入) │
│ → 弹出 tkinter 文件选择对话框 │
│ ├─ 选择了文件? → 使用该路径 │
│ └─ 取消了? → 返回 None │
└─────────────────────────────────────────┘
```
**具体改动**
- 修改 `file_selector.py` 中的 `select_file()` 函数
- 新增路径验证逻辑(`os.path.exists()` + 文件扩展名检查)
- 新增循环重试逻辑(路径不存在时提示重新输入,最多重试 N 次或无限重试)
- 保留 tkinter 弹窗作为空输入时的回退方案
### 2.3 需求 R3窗口属性
**现状**
- 项目没有 bat 启动脚本
- 用户通过 `python main.py``python main.py input.xls` 直接运行
- 窗口属性完全依赖用户 CMD 默认设置
**修改目标**
创建 `run.bat` 作为标准启动入口,配置窗口属性。
**bat 脚本内容**
```bat
@ECHO OFF
chcp 65001
title PinMAP转PinList -By:LeeQwQ
mode con cols=80 lines=20
color 0B
cls
python main.py %*
pause
EXIT
```
**属性说明**
| 属性 | 命令 | 效果 |
|------|------|------|
| 编码 | `chcp 65001` | 设置 UTF-8 编码,正确显示中文 |
| 窗口标题 | `title PinMAP转PinList -By:LeeQwQ` | 固定署名 |
| 窗口大小 | `mode con cols=80 lines=20` | 80列 × 20行可见区域 |
| 颜色 | `color 0B` | 黑底(0) + 青字(B/浅蓝) |
| 清屏 | `cls` | 启动时清除历史输出 |
| 暂停退出 | `pause` | 转换完成后等待按键 |
**关于"支持往上滑看历史 log 输出信息"**
- `mode con lines=20` 设置的是**可见窗口行数**20行不是缓冲区大小
- Windows CMD 默认的**屏幕缓冲区高度**为 300 行
- 即使可见区域只有 20 行,用户仍可以通过鼠标滚轮或滚动条向上滚动查看历史输出
- 如果需要更大的缓冲区,可额外设置:`mode con cols=80 lines=20` 后,缓冲区默认 300 行已足够
- 如需显式指定缓冲区(可选):可通过注册表或 `mode con` 的缓冲区参数,但通常不需要
**关于"报错时重新输入(不退出)"**
- R2 的文件选择循环已覆盖此场景(路径不存在时返回重试)
- 其他阶段的错误(文件读取失败、结构错误等)仍会退出,但 `pause` 确保窗口不关闭,用户可以看到错误信息
---
## 3. 影响模块列表
| 模块 | 文件 | 影响程度 | 修改内容 | 关联需求 |
|------|------|---------|---------|---------|
| **入口流程** | `src/main.py` | **高** | 增加启动 Banner、详细日志、结果摘要、任意键退出 | R1, R3 |
| **文件选择** | `src/file_selector.py` | **高** | 重写 `select_file()`:路径输入 → 验证 → 弹窗回退 → 循环重试 | R2 |
| **启动脚本** | `run.bat`(新建) | **中** | 创建 bat 启动脚本,配置窗口属性 | R3 |
| **工具函数** | `src/utils.py` | 无 | 无需修改 | — |
| **数据模型** | `src/models.py` | 无 | 无需修改 | — |
| **Excel 读写** | `src/xls_reader.py`<br>`src/xlsx_reader.py`<br>`src/xlsx_writer.py` | 无 | 无需修改 | — |
| **PinMAP 解析** | `src/pinmap_parser.py` | 无 | 无需修改 | — |
| **数据验证** | `src/validator.py` | 无 | 无需修改 | — |
| **PinList 生成** | `src/pinlist_generator.py` | 无 | 无需修改 | — |
**总结**:仅需修改 **2 个现有文件** + 新建 **1 个 bat 脚本**,其余 6 个核心业务模块完全不受影响。
---
## 4. 技术方案
### 4.1 R1 技术方案:交互提示
#### 4.1.1 启动 Banner
`main.py``main()` 函数开头添加:
```python
def show_banner():
"""显示程序启动 Banner"""
print("=" * 56)
print(" PinMAP → PinList 转换器")
print(" 自动将 Excel PinMAP 文件转换为 PinList")
print()
print(" 版本: v1.0.1")
print(" -By: LeeQwQ")
print("=" * 56)
print()
```
#### 4.1.2 详细日志
在现有流程的每个阶段增加日志输出:
```python
# 文件读取前
print(f"[INFO] 正在读取文件: {filepath}")
# 文件读取后
print(f"[INFO] 文件读取完成,共 {len(cells)} 个非空单元格")
# PinMAP 解析前
print(f"[INFO] 正在解析 PinMAP 结构...")
# 验证前
print(f"[INFO] 正在验证数据...")
# 验证后(已有)
print(f"[INFO] 验证通过,{len(validation.errors)} 个错误,{len(validation.warnings)} 个警告")
# 生成前
print(f"[INFO] 正在生成 PinList...")
# 写入前
print(f"[INFO] 正在写入输出文件: {output_path}")
```
#### 4.1.3 结果摘要 + 任意键退出
`main()` 末尾(所有成功/失败分支)添加:
```python
def show_summary(input_path, output_path, pinlist, validation):
"""显示转换结果摘要"""
print()
print("=" * 56)
print(" 转换结果摘要")
print("=" * 56)
print(f" 输入文件: {input_path}")
print(f" 输出文件: {output_path}")
print(f" 封装信息: {pinlist.package_info}")
print(f" Pin 数量: {len(pinlist.rows)}")
print(f" 错误数量: {len(validation.errors)}")
print(f" 警告数量: {len(validation.warnings)}")
print("=" * 56)
def wait_for_exit():
"""等待用户按键后退出"""
try:
import msvcrt
print("\n按任意键退出...")
msvcrt.getch() # Windows 专属,无需回车
except ImportError:
input("\n按 Enter 键退出...") # 跨平台回退
```
**技术要点**
- 使用 `msvcrt.getch()` 实现 Windows 上的"任意键退出"(无需按 Enter
- 跨平台回退使用 `input()`
- 结果摘要仅在成功转换时显示;错误时直接显示错误信息 + 等待退出
### 4.2 R2 技术方案:文件选择方式调整
#### 4.2.1 新的 `select_file()` 流程
```python
def select_file() -> Optional[str]:
"""
文件选择流程:
1. 提示用户输入文件路径
2. 空输入 → 弹出 tkinter 文件对话框
3. 有输入但路径不存在 → 报错 + 重新输入
4. 有输入且路径存在 → 返回路径
"""
while True:
# Step 1: 用户输入路径
filepath = input("请输入 PinMAP 文件路径(直接回车使用文件选择器): ").strip()
# Step 2: 空输入 → 弹窗
if not filepath:
return _select_file_dialog()
# Step 3: 路径验证
if not os.path.exists(filepath):
print(f"[ERROR] 文件不存在: {filepath}")
print("请重新输入...")
continue
# Step 4: 扩展名检查
if not filepath.lower().endswith(('.xls', '.xlsx')):
print(f"[WARN] 文件扩展名不是 .xls 或 .xlsx是否继续")
confirm = input("输入 Y 继续,其他键重新输入: ").strip().upper()
if confirm != 'Y':
continue
return filepath
```
#### 4.2.2 弹窗回退函数
```python
def _select_file_dialog() -> Optional[str]:
"""弹出 tkinter 文件选择对话框"""
try:
import tkinter
import tkinter.filedialog
root = tkinter.Tk()
root.withdraw()
root.attributes("-topmost", True)
filepath = tkinter.filedialog.askopenfilename(
title="选择 PinMAP 文件",
filetypes=[
("Excel 文件", "*.xls *.xlsx"),
("所有文件", "*.*"),
],
)
root.destroy()
return str(filepath) if filepath else None
except (ImportError, Exception):
print("[ERROR] 无法打开文件选择器,请手动输入路径")
return None
```
**技术要点**
- 使用 `while True` 循环实现路径不存在时的重试
- 扩展名检查为 WARN 级别(允许用户强制继续)
- 弹窗回退函数独立封装,保持代码清晰
### 4.3 R3 技术方案:窗口属性
#### 4.3.1 创建 `run.bat`
在项目根目录创建 `run.bat`
```bat
@ECHO OFF
chcp 65001 >nul
title PinMAP转PinList -By:LeeQwQ
mode con cols=80 lines=20
color 0B
cls
python main.py %*
pause
EXIT
```
**说明**
- `chcp 65001 >nul`:静默设置 UTF-8 编码,避免输出 `Active code page: 65001` 干扰界面
- `%*`:透传所有命令行参数(如 `run.bat input.xls`
- `pause`:确保窗口不自动关闭
- `EXIT`:按键后退出 CMD
#### 4.3.2 关于"支持往上滑看历史 log"
- Windows CMD 默认屏幕缓冲区高度为 **300 行**
- `mode con lines=20` 仅设置可见窗口为 20 行,**不影响缓冲区**
- 用户可通过鼠标滚轮或滚动条向上滚动查看完整日志历史
- 如需显式增大缓冲区(可选),可在 bat 中通过 PowerShell 设置,但通常 300 行已足够
#### 4.3.3 关于"报错时重新输入(不退出)"
- R2 的文件选择循环已覆盖"路径不存在"场景
- 其他阶段报错(文件读取失败、结构错误等)会退出 `main()` 但被 `pause` 拦截
- 窗口不会关闭,用户可阅读错误信息后按任意键退出
---
## 5. 任务拆分建议
### 5.1 拆分方案
由于修改范围小2 个文件 + 1 个新文件),**建议不拆分**,由单个编码 Agent 完成。
| 子任务 | 文件 | 预估工作量 | 依赖 |
|--------|------|-----------|------|
| T1: 交互提示 | `src/main.py` | 30 分钟 | 无 |
| T2: 文件选择调整 | `src/file_selector.py` | 20 分钟 | 无 |
| T3: 启动脚本 | `run.bat` | 5 分钟 | 无 |
**总计预估**:约 1 小时
### 5.2 推荐编码 Agent
**Python 编码 Agent**(单个 Agent 即可完成)
理由:
1. 修改不涉及核心业务逻辑(解析、验证、生成)
2. 纯 Python 标准库实现,无第三方依赖
3. bat 脚本简单,任何 Agent 均可完成
4. 拆分反而增加沟通成本
### 5.3 开发顺序
```
T2文件选择 → T1交互提示 → T3启动脚本 → 集成测试
```
理由T2 和 T1 都修改 `main.py`,建议先完成 T2file_selector.py 独立),再合并 T1 到 main.py避免冲突。
---
## 6. 风险评估
| 风险 | 影响 | 概率 | 缓解措施 |
|------|------|------|---------|
| `msvcrt.getch()` 在非 Windows 平台不可用 | 低 | 低 | 已设计跨平台回退(`input()` |
| tkinter 在无 GUI 环境不可用 | 低 | 低 | 已设计回退到路径输入模式 |
| `mode con lines=20` 窗口过小导致日志被截断 | 中 | 中 | 缓冲区默认 300 行,可滚动查看;如需调整可修改 lines 参数 |
| 用户输入路径含特殊字符(空格、中文) | 低 | 中 | Python `os.path.exists()` 和 Excel 读写引擎已支持 Unicode |
| bat 脚本中 `python` 命令不在 PATH 中 | 中 | 中 | 可在 bat 中使用 `py` 命令替代Windows Python Launcher |
### 6.1 技术难点
**无重大技术难点**。所有需求均使用 Python 标准库实现:
- 交互提示:`print()` + `input()` + `msvcrt`
- 文件选择:`os.path.exists()` + `tkinter.filedialog`
- 窗口属性bat 内置命令
### 6.2 兼容性考虑
| 场景 | 处理方式 |
|------|---------|
| 双击 `run.bat` 运行 | 正常流程,窗口不关闭 |
| `run.bat input.xls` 带参数 | `%*` 透传,跳过文件选择 |
| 直接 `python main.py`(不用 bat | 交互提示仍生效,但窗口属性不生效(预期行为) |
| 无 GUI 环境(服务器/远程桌面) | 文件选择回退到路径输入模式 |
| 非 Windows 平台 | `msvcrt` 回退到 `input()`bat 不适用 |
---
## 7. 修改后目录结构
```
pinmap-to-pinlist/
├── Code/
│ ├── src/
│ │ ├── main.py # ✏️ 修改:增加 Banner、日志、摘要
│ │ ├── file_selector.py # ✏️ 修改:重写 select_file()
│ │ ├── xls_reader.py # (不变)
│ │ ├── xlsx_reader.py # (不变)
│ │ ├── pinmap_parser.py # (不变)
│ │ ├── validator.py # (不变)
│ │ ├── pinlist_generator.py # (不变)
│ │ ├── xlsx_writer.py # (不变)
│ │ ├── models.py # (不变)
│ │ └── utils.py # (不变)
│ └── docs/
│ ├── architecture-design.md # (不变)
│ └── modification-assessment.md # 🆕 本文档
├── run.bat # 🆕 新建:启动脚本
├── Test/
└── Releases/
```
---
## 8. 总结
| 项目 | 内容 |
|------|------|
| 修改文件数 | 2 个现有 + 1 个新建 |
| 影响核心模块 | 无(仅修改入口和文件选择) |
| 技术难度 | 低 |
| 预估工作量 | ~1 小时 |
| 推荐 Agent | Python 编码 Agent单个 |
| 风险等级 | 低 |
**结论**:修改需求清晰、范围可控、无技术难点,建议直接分配给单个编码 Agent 执行。
---
*文档结束 — 请审批后进入编码阶段*