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:
471
Code/docs/modification-assessment.md
Normal file
471
Code/docs/modification-assessment.md
Normal 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`,建议先完成 T2(file_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 执行。
|
||||
|
||||
---
|
||||
|
||||
*文档结束 — 请审批后进入编码阶段*
|
||||
Reference in New Issue
Block a user