v1.3.0: 修复pinmap_layout周长公式,新增PinList→PinMAP反向转换完整支持

This commit is contained in:
2026-06-01 11:43:53 +08:00
parent 3228c1a2e6
commit 8ad31cbf04
16 changed files with 967 additions and 183 deletions

View File

@@ -33,6 +33,29 @@ def wait_for_exit():
# ── Path helpers ────────────────────────────────────────────────────
def _find_template_path() -> str | None:
"""查找根目录下的 PinMAP-Template.xlsx。
搜索顺序:
1. 与 run.bat 同级的根目录
2. 当前工作目录
"""
# 从 Code/src 回退到根目录
src_dir = os.path.dirname(os.path.abspath(__file__))
root_dir = os.path.dirname(os.path.dirname(src_dir)) # pinmap-to-pinlist/
template_path = os.path.join(root_dir, "PinMAP-Template.xlsx")
if os.path.exists(template_path):
return template_path
# 回退到当前工作目录
cwd_template = os.path.join(os.getcwd(), "PinMAP-Template.xlsx")
if os.path.exists(cwd_template):
return cwd_template
return None
def _build_output_path_map_to_list(input_path: str) -> str:
"""Generate output path: {original_filename}_PinList.xlsx"""
base, _ = os.path.splitext(input_path)
@@ -55,7 +78,8 @@ def run_map_to_list(filepath: str):
from pinmap_parser import parse_pinmap
from validator import validate_pinmap
from pinlist_generator import generate_pinlist
from xlsx_writer import write_xlsx
from xlsx_writer import write_xlsx, write_xlsx_with_style
from template_reader import read_template_styles
from models import FileFormatError, StructureError
# ── 1. File selection ───────────────────────────────────────────
@@ -126,7 +150,22 @@ def run_map_to_list(filepath: str):
data[f'A{row}'] = pin_name
data[f'B{row}'] = str(pin_num)
write_xlsx(data, output_path)
# 尝试读取模板样式F007
template_path = _find_template_path()
template_style = None
if template_path:
template_style = read_template_styles(template_path)
if template_style:
print(f"[INFO] 已加载模板样式: {template_path}")
else:
print("[WARN] 模板文件存在但解析失败,使用默认样式")
else:
print("[INFO] 未检测到模板文件,使用默认样式")
if template_style is not None:
write_xlsx_with_style(data, output_path, template_style)
else:
write_xlsx(data, output_path)
except Exception as e:
print(f"[FATAL] 输出失败: {e}")
wait_for_exit()
@@ -139,7 +178,7 @@ def run_map_to_list(filepath: str):
print(f" 封装信息: {pinlist.package_info}")
print(f" Pin数量: {len(pinlist.rows)}")
wait_for_exit()
# F008: 不再退出,返回主循环
# ── Direction 2: List → MAP ────────────────────────────────────────
@@ -221,8 +260,17 @@ def run_list_to_map(filepath: str):
print(f"[INFO] 正在生成 PinMAP 并写入: {output_path}")
try:
# 尝试读取模板样式(优雅降级
template_style = read_template_styles(filepath)
# 尝试读取模板样式(F007 — 从根目录读取而非输入文件路径
template_path = _find_template_path()
template_style = None
if template_path:
template_style = read_template_styles(template_path)
if template_style:
print(f"[INFO] 已加载模板样式: {template_path}")
else:
print("[WARN] 模板文件存在但解析失败,使用默认样式")
else:
print("[INFO] 未检测到模板文件,使用默认样式")
generate_pinmap(
entries=entries,
@@ -249,7 +297,7 @@ def run_list_to_map(filepath: str):
print(f" PinMAP 尺寸: {rows}×{cols}")
print(f" Pin数量: {len(entries)}")
wait_for_exit()
# F008: 不再退出,返回主循环
# ── Main entry ──────────────────────────────────────────────────────
@@ -257,41 +305,59 @@ def run_list_to_map(filepath: str):
def main():
show_banner()
# ── Direction selection ─────────────────────────────────────────
if len(sys.argv) > 1:
# Legacy mode: direct file argument → MAP→List
direction = 1
filepath = sys.argv[1]
else:
print("请选择转换方向:")
print(" 1 — PinMAP → PinList")
print(" 2 — PinList → PinMAP")
print()
# F008: 循环处理流程
while True:
# ── Direction selection ─────────────────────────────────────
if len(sys.argv) > 1:
# Legacy mode: direct file argument → MAP→List
direction = 1
filepath = sys.argv[1]
sys.argv = [sys.argv[0]] # 清除 argv下次循环进入交互模式
else:
print("请选择转换方向:")
print(" 1 — PinMAP → PinList")
print(" 2 — PinList → PinMAP")
print(" Q — 退出程序")
print()
while True:
choice = input("请输入选项 (1/2): ").strip()
if choice in ('1', '2'):
direction = int(choice)
break
print("[ERROR] 无效选项,请输入 1 或 2")
choice = input("请输入选项 (1/2/Q): ").strip().upper()
if choice == 'Q':
print("感谢使用,再见!")
return
elif choice == '1':
direction = 1
elif choice == '2':
direction = 2
else:
print("[ERROR] 无效选项,请输入 1、2 或 Q")
continue
filepath = None # will be selected inside the flow
filepath = None
# ── Dispatch ────────────────────────────────────────────────────
if direction == 1:
# ── Dispatch ────────────────────────────────────────────────
if direction == 1:
print()
print("" * 40)
print(" 方向: PinMAP → PinList")
print("" * 40)
print()
run_map_to_list(filepath)
else:
print()
print("" * 40)
print(" 方向: PinList → PinMAP")
print("" * 40)
print()
run_list_to_map(filepath)
# ── 处理完成后循环 ──────────────────────────────────────────
print()
print("" * 40)
print(" 方向: PinMAP → PinList")
print("" * 40)
print()
run_map_to_list(filepath)
else:
print()
print("" * 40)
print(" 方向: PinList → PinMAP")
print("" * 40)
print()
run_list_to_map(filepath)
print("=" * 40)
next_choice = input("输入 Q 退出,或按 Enter 返回主菜单继续转换: ").strip().upper()
if next_choice == 'Q':
print("感谢使用,再见!")
return
# 否则继续 while 循环,回到主菜单
if __name__ == '__main__':