Track the source-of-truth code, skills, bootstrap rules, docs, and packaging files before adding new features. Exclude local vault config, generated skill mirrors, temporary exports, virtual environments, and business data files from version control. Validation: inspected staged file list and git ignored status before commit.
553 lines
22 KiB
Python
553 lines
22 KiB
Python
#!/usr/bin/env python3
|
||
"""Ingest archived public competitor sources into the BJD mother vault."""
|
||
|
||
from __future__ import annotations
|
||
|
||
import json
|
||
from datetime import datetime, timezone
|
||
from pathlib import Path
|
||
|
||
|
||
VAULT = Path("/home/nac/repo/obsidian-wiki-linux/kb/bjd-vault")
|
||
RESULTS = Path("/tmp/bjd_competitor_download_results.json")
|
||
NOW = datetime.now(timezone.utc).replace(microsecond=0).isoformat().replace("+00:00", "Z")
|
||
|
||
|
||
def load_results() -> list[dict]:
|
||
return json.loads(RESULTS.read_text(encoding="utf-8"))
|
||
|
||
|
||
def source_type(item: dict) -> str:
|
||
if item.get("type"):
|
||
return item["type"]
|
||
name = item["name"].lower()
|
||
if name.endswith(".pdf"):
|
||
return "pdf"
|
||
if name.endswith(".zip"):
|
||
return "cad"
|
||
return "web"
|
||
|
||
|
||
def doc_type(item: dict) -> str:
|
||
name = item["name"].lower()
|
||
if "drawing" in name or "dxf" in name:
|
||
return "drawing"
|
||
if "step" in name:
|
||
return "cad_model"
|
||
if "catalog" in name or "guide" in name:
|
||
return "catalog"
|
||
if "manual" in name or "instruction" in name:
|
||
return "instruction_manual"
|
||
if "datasheet" in name or "spec-sheet" in name or "whitepaper" in name:
|
||
return "spec_sheet"
|
||
if "page" in name:
|
||
return "product_page"
|
||
return "product_parameter"
|
||
|
||
|
||
def product_line(item: dict) -> list[str]:
|
||
series = item.get("series", "")
|
||
brand = item.get("brand", "")
|
||
if brand in {"Rosenberger"} or "hfm" in item["name"].lower():
|
||
return ["Mini FAKRA", "High Speed"]
|
||
if brand == "TE":
|
||
return ["I/O", "WTB", "Hybrid connector"]
|
||
if "mini50" in item["name"].lower():
|
||
return ["WTB", "Automotive wire-to-board"]
|
||
if series in {"FH52", "FH52K", "FH75", "FH64MA", "6817"}:
|
||
return ["FPC", "FFC"]
|
||
if brand == "IRISO":
|
||
return ["BTB", "FPC", "WTB"]
|
||
return ["Automotive connectors"]
|
||
|
||
|
||
def related_page(item: dict) -> str:
|
||
brand = item.get("brand", "")
|
||
series = item.get("series", "")
|
||
name = item["name"].lower()
|
||
if brand == "Hirose" and series in {"FH52", "FH52K"}:
|
||
return "projects/bjd/references/hirose-fh52-fh52k-public-sources-20260605.md"
|
||
if brand == "Hirose" and series == "FH75":
|
||
return "projects/bjd/references/hirose-fh75-fh75m-automotive-fpc-connector.md"
|
||
if brand in {"Hirose", "Kyocera"} and series in {"FH64MA", "6817"}:
|
||
return "projects/bjd/references/hirose-fh64ma-kyocera-6817-fpc-connectors.md"
|
||
if brand == "TE" or "73pos" in name:
|
||
return "projects/bjd/references/te-2188698-73pin-hybrid-connector-public-sources-20260605.md"
|
||
if brand == "Molex":
|
||
return "projects/bjd/references/molex-mini50-connector-system.md"
|
||
if brand == "IRISO":
|
||
return "projects/bjd/references/iriso-public-competitor-sources-20260605.md"
|
||
if brand == "Rosenberger":
|
||
return "projects/bjd/references/bjd-mini-fakra-product-and-test-evidence.md"
|
||
return "projects/bjd/references/competitor-public-source-archive-20260605.md"
|
||
|
||
|
||
def summary_for(item: dict) -> str:
|
||
brand = item.get("brand", "Competitor")
|
||
series = item.get("series", "")
|
||
dtype = doc_type(item).replace("_", " ")
|
||
if series:
|
||
return f"{brand} {series} official public {dtype} archived for BJD competitor lookup and replacement evaluation."
|
||
return f"{brand} official public {dtype} archived for BJD competitor lookup and replacement evaluation."
|
||
|
||
|
||
def registry_records(items: list[dict]) -> list[dict]:
|
||
records = []
|
||
for item in items:
|
||
if not item.get("ok"):
|
||
continue
|
||
brand = item.get("brand", "unknown")
|
||
stype = source_type(item)
|
||
rec = {
|
||
"record_type": "source_archive",
|
||
"source_id": f"sha256:{item['sha256']}",
|
||
"archived_at": NOW,
|
||
"archive_path": item["archive_path"],
|
||
"original_path": item["url"],
|
||
"original_name": item["name"],
|
||
"source_type": stype,
|
||
"doc_type": doc_type(item),
|
||
"business_categories": [f"competitors/{brand.lower()}", "products/automotive-connectors"],
|
||
"product_lines": product_line(item),
|
||
"customers": [],
|
||
"competitors": [brand],
|
||
"standards": [],
|
||
"market_tags": ["market/automotive"],
|
||
"title": item["name"].rsplit(".", 1)[0],
|
||
"summary": summary_for(item),
|
||
"visibility": "internal",
|
||
"data_classification": "public-web",
|
||
"allowed_bots": ["bjd-general-bot"],
|
||
"classification_confidence": 0.84,
|
||
"classification_evidence": ["official vendor public source", f"downloaded from {item['url']}"],
|
||
"catalog_paths": [f"_sources/catalog/bjd/competitors/{brand.lower()}.md"],
|
||
"project": "bjd",
|
||
"size_bytes": item.get("size_bytes"),
|
||
"modified_at": None,
|
||
"related_pages": [related_page(item)],
|
||
"bjd_part_numbers": [],
|
||
"competitor_part_numbers": [item.get("series")] if item.get("series") else [],
|
||
"series": [item.get("series")] if item.get("series") else [],
|
||
"pin_count": 73 if "73pos" in item["name"].lower() else None,
|
||
"needs_review": 0,
|
||
}
|
||
records.append(rec)
|
||
return records
|
||
|
||
|
||
def append_registry(records: list[dict]) -> int:
|
||
path = VAULT / "_meta/source-registry.jsonl"
|
||
existing = path.read_text(encoding="utf-8") if path.exists() else ""
|
||
existing_ids = set()
|
||
for line in existing.splitlines():
|
||
try:
|
||
existing_ids.add(json.loads(line).get("source_id"))
|
||
except json.JSONDecodeError:
|
||
pass
|
||
new = [r for r in records if r["source_id"] not in existing_ids]
|
||
if new:
|
||
with path.open("a", encoding="utf-8") as f:
|
||
for rec in new:
|
||
f.write(json.dumps(rec, ensure_ascii=False, sort_keys=False) + "\n")
|
||
return len(new)
|
||
|
||
|
||
def md_link(item: dict) -> str:
|
||
path = item.get("archive_path")
|
||
if path:
|
||
return f"[{item['name']}]({path})"
|
||
return f"[{item['name']}]({item['url']})"
|
||
|
||
|
||
def registry_competitor_items() -> list[dict]:
|
||
path = VAULT / "_meta/source-registry.jsonl"
|
||
if not path.exists():
|
||
return []
|
||
items = []
|
||
for line in path.read_text(encoding="utf-8").splitlines():
|
||
if not line.strip():
|
||
continue
|
||
try:
|
||
rec = json.loads(line)
|
||
except json.JSONDecodeError:
|
||
continue
|
||
categories = rec.get("business_categories") or []
|
||
competitors = rec.get("competitors") or []
|
||
if not any(str(c).startswith("competitors/") for c in categories) and not competitors:
|
||
continue
|
||
vendor = competitors[0] if competitors else None
|
||
if not vendor:
|
||
for c in categories:
|
||
if str(c).startswith("competitors/"):
|
||
vendor = str(c).split("/", 1)[1].upper()
|
||
break
|
||
if not vendor:
|
||
continue
|
||
item = {
|
||
"ok": True,
|
||
"name": rec.get("original_name") or rec.get("title") or rec.get("source_id"),
|
||
"type": rec.get("source_type") or "web",
|
||
"brand": vendor,
|
||
"series": (rec.get("series") or rec.get("competitor_part_numbers") or [""])[0],
|
||
"archive_path": rec.get("archive_path"),
|
||
"size_bytes": rec.get("size_bytes") or "",
|
||
"url": rec.get("original_path") or "",
|
||
"_registry_doc_type": rec.get("doc_type") or "product_parameter",
|
||
}
|
||
items.append(item)
|
||
return items
|
||
|
||
|
||
def vendor_catalog(vendor: str, items: list[dict]) -> str:
|
||
good = [i for i in items if i.get("ok") and i.get("brand") == vendor]
|
||
failed = [i for i in items if not i.get("ok") and i.get("brand") == vendor]
|
||
slug = vendor.lower()
|
||
title = f"{vendor} 竞品源文件目录"
|
||
rows = []
|
||
for item in sorted(good, key=lambda x: (x.get("series") or "", x["name"])):
|
||
rows.append(
|
||
f"| {md_link(item)} | {item.get('_registry_doc_type') or doc_type(item)} | {item.get('series','')} | {item.get('size_bytes','')} | [source]({item['url']}) |"
|
||
)
|
||
failed_lines = ""
|
||
if failed:
|
||
failed_lines = "\n\n## 待补链接\n\n" + "\n".join(
|
||
f"- {i['name']} - 下载失败,需从官方页面重新确认直链:{i['url']}" for i in failed
|
||
)
|
||
return f"""---
|
||
title: {title}
|
||
category: meta
|
||
tags: [source-catalog, bjd, competitors, {slug}, visibility/internal]
|
||
sources:
|
||
- _meta/source-registry.jsonl
|
||
created: 2026-06-05
|
||
updated: {NOW}
|
||
---
|
||
|
||
# {title}
|
||
|
||
本页记录已归档到母库的 {vendor} 官方公开竞品资料。资料可用于竞品识别、替代评估、图纸/规格书检索;不要把“有公开资料”自动解释为 BJD 已完成 drop-in 替代。
|
||
|
||
| 归档文件 | 类型 | 系列 | 大小 bytes | 原始官方链接 |
|
||
|---|---|---:|---:|---|
|
||
{chr(10).join(rows) if rows else '| 暂无 | | | | |'}
|
||
{failed_lines}
|
||
|
||
## 相关页面
|
||
|
||
- [[projects/bjd/references/competitor-public-source-archive-20260605]]
|
||
- [[projects/bjd/references/competitor-cross-reference-map]]
|
||
"""
|
||
|
||
|
||
def index_catalog(items: list[dict]) -> str:
|
||
vendors = sorted({i.get("brand", "unknown") for i in items if i.get("brand")})
|
||
lines = []
|
||
for vendor in vendors:
|
||
good = sum(1 for i in items if i.get("brand") == vendor and i.get("ok"))
|
||
failed = sum(1 for i in items if i.get("brand") == vendor and not i.get("ok"))
|
||
note = f"{good} 个已归档"
|
||
if failed:
|
||
note += f",{failed} 个待补"
|
||
lines.append(f"- [[_sources/catalog/bjd/competitors/{vendor.lower()}]] - {vendor},{note}。")
|
||
return f"""---
|
||
title: BJD 竞品资料源文件目录
|
||
category: meta
|
||
tags: [source-catalog, bjd, competitors, visibility/internal]
|
||
sources:
|
||
- _meta/source-registry.jsonl
|
||
created: 2026-06-03
|
||
updated: {NOW}
|
||
---
|
||
|
||
# BJD 竞品资料源文件目录
|
||
|
||
该目录记录 BJD wiki 已归档的竞品公开资料,包括官方产品页、目录、规格书、2D 图纸、CAD/STEP/DFX 压缩包和操作说明。归档资料用于后续检索和替代评估。
|
||
|
||
{chr(10).join(lines)}
|
||
|
||
## 总索引
|
||
|
||
- [[projects/bjd/references/competitor-public-source-archive-20260605]] - 2026-06-05 竞品公开资料归档总览。
|
||
"""
|
||
|
||
|
||
def master_page(items: list[dict]) -> str:
|
||
by_vendor: dict[str, list[dict]] = {}
|
||
for item in items:
|
||
if item.get("ok"):
|
||
by_vendor.setdefault(item.get("brand", "unknown"), []).append(item)
|
||
sections = []
|
||
for vendor, rows in sorted(by_vendor.items()):
|
||
lines = [
|
||
f"| {i.get('series','')} | {md_link(i)} | {doc_type(i)} | [official]({i['url']}) |"
|
||
for i in sorted(rows, key=lambda x: (x.get("series") or "", x["name"]))
|
||
]
|
||
sections.append(f"## {vendor}\n\n| 系列 | 归档文件 | 类型 | 原始链接 |\n|---|---|---|---|\n" + "\n".join(lines))
|
||
failed = [i for i in items if not i.get("ok")]
|
||
failed_text = "\n".join(f"- {i.get('brand')} {i.get('series')}: {i['name']} - {i['url']}" for i in failed)
|
||
return f"""---
|
||
title: 2026-06-05 竞品公开资料归档总览
|
||
category: references
|
||
tags: [bjd, competitors, public-sources, drawings, catalogs, visibility/internal]
|
||
visibility: internal
|
||
business_domains: [products, sales, engineering]
|
||
data_classification: public-web
|
||
allowed_bots: [bjd-general-bot]
|
||
sources:
|
||
- _meta/source-registry.jsonl
|
||
summary: 2026-06-05 联网补充并归档 Hirose、TE、IRISO、Kyocera、Rosenberger 等竞品官方公开资料,覆盖产品页、目录、规格书、2D 图纸和 CAD/STEP/DFX 文件。
|
||
relationships:
|
||
- target: "[[projects/bjd/references/competitor-cross-reference-map]]"
|
||
type: supports
|
||
- target: "[[projects/bjd/references/bjd-fpc-cross-reference-20260422]]"
|
||
type: supports
|
||
- target: "[[projects/bjd/references/bjd-io-cross-reference-20260422]]"
|
||
type: supports
|
||
- target: "[[projects/bjd/references/bjd-wtb-hs-cross-reference-20260422]]"
|
||
type: supports
|
||
provenance:
|
||
extracted: 0.88
|
||
inferred: 0.09
|
||
ambiguous: 0.03
|
||
base_confidence: 0.87
|
||
lifecycle: draft
|
||
lifecycle_changed: 2026-06-05
|
||
tier: core
|
||
created: 2026-06-05T00:00:00Z
|
||
updated: {NOW}
|
||
---
|
||
|
||
# 2026-06-05 竞品公开资料归档总览
|
||
|
||
本页是竞品官方公开资料的检索入口。已归档文件保存在 `_sources/archive/bjd/2026-06/competitor/`,并写入 `_meta/source-registry.jsonl`。这些资料用于识别竞品结构、pin 数、规格书、图纸、land pattern、CAD/STEP/DFX 文件和替代评估边界;不能单独作为 BJD 已经完成完全替代或 drop-in 的证据。
|
||
|
||
{chr(10).join(sections)}
|
||
|
||
## 待补链接
|
||
|
||
以下官方直链下载失败,已记录为待补,不计入已归档文件:
|
||
|
||
{failed_text if failed_text else "- 无。"}
|
||
|
||
## 使用口径
|
||
|
||
- 客户只给竞品料号时,先查本页或对应厂牌 catalog,确认官方图纸/规格书是否已归档。
|
||
- 有 2D 图纸、STEP/DXF 时,仍需工程复核 FPC/FFC 厚度、tab、land pattern、焊盘、插入方向、锁扣、温度等级和可靠性要求。
|
||
- 公开竞品资料只用于技术对标;对外报价、具体客户价格、交货数量仍按 [[projects/bjd/references/bjd-general-bot-answer-policy]] 的敏感信息边界处理。
|
||
|
||
## 相关页面
|
||
|
||
- [[projects/bjd/references/competitor-cross-reference-map]]
|
||
- [[projects/bjd/references/hirose-fh52-fh52k-public-sources-20260605]]
|
||
- [[projects/bjd/references/te-2188698-73pin-hybrid-connector-public-sources-20260605]]
|
||
- [[projects/bjd/references/iriso-public-competitor-sources-20260605]]
|
||
- [[projects/bjd/references/hirose-fh75-fh75m-automotive-fpc-connector]]
|
||
- [[projects/bjd/references/hirose-fh64ma-kyocera-6817-fpc-connectors]]
|
||
- [[projects/bjd/references/molex-mini50-connector-system]]
|
||
"""
|
||
|
||
|
||
def fh52_page(items: list[dict]) -> str:
|
||
rows = [i for i in items if i.get("ok") and i.get("brand") == "Hirose" and i.get("series") in {"FH52", "FH52K"}]
|
||
lines = "\n".join(f"| {i.get('series')} | {md_link(i)} | {doc_type(i)} | [official]({i['url']}) |" for i in rows)
|
||
return f"""---
|
||
title: Hirose FH52/FH52K 官方公开资料归档
|
||
category: references
|
||
tags: [hirose, fh52, fh52k, fpc, ffc, cross-reference, visibility/internal]
|
||
visibility: internal
|
||
business_domains: [products, sales, engineering]
|
||
data_classification: public-web
|
||
allowed_bots: [bjd-general-bot]
|
||
sources:
|
||
- _meta/source-registry.jsonl
|
||
summary: Hirose FH52/FH52K 官方产品页、目录、2D 图纸、规格书和 STEP 资料归档,用于 FH52-30S-0.5SH 等料号的替代评估。
|
||
relationships:
|
||
- target: "[[projects/bjd/references/bjd-fpc-cross-reference-20260422]]"
|
||
type: supports
|
||
- target: "[[projects/bjd/references/hirose-fh75-fh75m-automotive-fpc-connector]]"
|
||
type: related_to
|
||
provenance:
|
||
extracted: 0.86
|
||
inferred: 0.10
|
||
ambiguous: 0.04
|
||
base_confidence: 0.86
|
||
lifecycle: draft
|
||
lifecycle_changed: 2026-06-05
|
||
tier: core
|
||
created: 2026-06-05T00:00:00Z
|
||
updated: {NOW}
|
||
---
|
||
|
||
# Hirose FH52/FH52K 官方公开资料归档
|
||
|
||
客户问 `FH52-30S-0.5SH`、`FH52K` 或 FH52/FH75 相邻替代时,优先查本页归档的官方产品页、目录、2D 图纸、规格书和 STEP 文件。BJD 已有 FPC `0.5-18` / `101049-X0XXX0` 对 HRS `FH52/FH28` 的对照线索;具体 30Pin 候选如 `101049-203050` 仍需按客户图纸复核 FPC 厚度、tab、land pattern、下接点/上接点、锁扣方向、连接器高度和包装。
|
||
|
||
| 系列 | 归档文件 | 类型 | 原始链接 |
|
||
|---|---|---|---|
|
||
{lines}
|
||
|
||
## 回答边界
|
||
|
||
- 可以说:BJD 有 FH52/FH28 对照链路,可从 FPC 0.5-18 系列评估。
|
||
- 不要直接承诺:完全 drop-in 或无需改板,除非工程已比对 Hirose 2D 图纸和客户 PCB/FPC。
|
||
- 网上能找到的 Hirose 图纸、规格书和 STEP,已尽量归档;后续客户只给 Hirose 料号时,先检索本页,不必第一时间麻烦客户。
|
||
|
||
## 相关页面
|
||
|
||
- [[projects/bjd/references/bjd-fpc-cross-reference-20260422]]
|
||
- [[projects/bjd/references/hirose-fh75-fh75m-automotive-fpc-connector]]
|
||
- [[projects/bjd/references/competitor-public-source-archive-20260605]]
|
||
"""
|
||
|
||
|
||
def te_page(items: list[dict]) -> str:
|
||
rows = [i for i in items if i.get("ok") and i.get("brand") == "TE"]
|
||
lines = "\n".join(f"| {i.get('series')} | {md_link(i)} | {doc_type(i)} | [official]({i['url']}) |" for i in rows)
|
||
return f"""---
|
||
title: TE 2188698 / 73Pin 混合端子官方公开资料归档
|
||
category: references
|
||
tags: [te, 2188698, 73pin, hybrid-connector, io, cross-reference, visibility/internal]
|
||
visibility: internal
|
||
business_domains: [products, sales, engineering]
|
||
data_classification: public-web
|
||
allowed_bots: [bjd-general-bot]
|
||
sources:
|
||
- _meta/source-registry.jsonl
|
||
summary: TE 2188698 相关 customer drawing、73pos instruction sheet 和 2D DXF 文件归档,用于 BJD 73Pin 混合端子产品对标。
|
||
relationships:
|
||
- target: "[[projects/bjd/references/bjd-io-cross-reference-20260422]]"
|
||
type: supports
|
||
- target: "[[projects/bjd/references/competitor-cross-reference-map]]"
|
||
type: related_to
|
||
provenance:
|
||
extracted: 0.84
|
||
inferred: 0.10
|
||
ambiguous: 0.06
|
||
base_confidence: 0.84
|
||
lifecycle: draft
|
||
lifecycle_changed: 2026-06-05
|
||
tier: core
|
||
created: 2026-06-05T00:00:00Z
|
||
updated: {NOW}
|
||
---
|
||
|
||
# TE 2188698 / 73Pin 混合端子官方公开资料归档
|
||
|
||
本页保存 TE `2188698` 相关公开图纸和 73pos instruction sheet 资料,用于评估 BJD `P2.0-2-73PIN` / `140084-417320` 这类 73Pin 混合端子产品。既有 wiki 记录显示该产品用于对标 TE `2420419-1` 方向,并与 TE `2188698` / `2188701` 相关配套项有关;具体替代需工程按 customer drawing、DXF、端子/壳体配合和客户应用确认。
|
||
|
||
| 系列 | 归档文件 | 类型 | 原始链接 |
|
||
|---|---|---|---|
|
||
{lines}
|
||
|
||
## 关键使用口径
|
||
|
||
- 可以把本页作为 TE 图纸和 2D CAD 检索入口。
|
||
- 不应仅凭 73Pin 和系列名承诺完全替代;混合端子需要复核机械界面、端子排布、锁止结构、线端/板端配套、材料和测试要求。
|
||
- TE 产品页 HTML 本次下载失败,已在厂牌 catalog 标为待补;PDF/DXF 资料已归档。
|
||
|
||
## 相关页面
|
||
|
||
- [[projects/bjd/references/bjd-io-cross-reference-20260422]]
|
||
- [[projects/bjd/references/competitor-cross-reference-map]]
|
||
- [[projects/bjd/references/competitor-public-source-archive-20260605]]
|
||
"""
|
||
|
||
|
||
def iriso_page(items: list[dict]) -> str:
|
||
rows = [i for i in items if i.get("ok") and i.get("brand") == "IRISO"]
|
||
lines = "\n".join(f"| {i.get('series')} | {md_link(i)} | {doc_type(i)} | [official]({i['url']}) |" for i in rows)
|
||
return f"""---
|
||
title: IRISO 公开竞品资料归档
|
||
category: references
|
||
tags: [iriso, btb, fpc, wtb, cross-reference, visibility/internal]
|
||
visibility: internal
|
||
business_domains: [products, sales, engineering]
|
||
data_classification: public-web
|
||
allowed_bots: [bjd-general-bot]
|
||
sources:
|
||
- _meta/source-registry.jsonl
|
||
summary: IRISO 13065、11507/11607、9827/9828/9860 和产品导览公开资料归档,用于 BJD WTB/BTB/FPC 竞品替代检索。
|
||
relationships:
|
||
- target: "[[projects/bjd/references/bjd-btb-cross-reference-20260422]]"
|
||
type: supports
|
||
- target: "[[projects/bjd/references/bjd-wtb-hs-cross-reference-20260422]]"
|
||
type: supports
|
||
provenance:
|
||
extracted: 0.84
|
||
inferred: 0.12
|
||
ambiguous: 0.04
|
||
base_confidence: 0.84
|
||
lifecycle: draft
|
||
lifecycle_changed: 2026-06-05
|
||
tier: core
|
||
created: 2026-06-05T00:00:00Z
|
||
updated: {NOW}
|
||
---
|
||
|
||
# IRISO 公开竞品资料归档
|
||
|
||
本页汇总 IRISO 官方公开资料。既有 BJD cross-reference 中 IRISO 涉及 FPC、浮动 BTB 和 WTB 多条线,尤其 `9827/9828` 浮动 BTB、`13065` WTB 以及 `11507/11607` 新闻资料。使用时应回到具体 BJD 系列和 pin 数做工程比对。
|
||
|
||
| 系列 | 归档文件 | 类型 | 原始链接 |
|
||
|---|---|---|---|
|
||
{lines}
|
||
|
||
## 检索建议
|
||
|
||
- 问 `IRISO 9827/9828/9860`:优先查浮动 BTB 归档 PDF,再回到 BJD BTB 对照页。
|
||
- 问 `IRISO 13065`:先查 13065 series page 和白皮书,再回到 BJD WTB/HS 对照页。
|
||
- 问 `IRISO 11507/11607`:本次归档的是官方新闻页,若后续找到单独 drawing/spec PDF,应继续补档。
|
||
|
||
## 相关页面
|
||
|
||
- [[projects/bjd/references/bjd-btb-cross-reference-20260422]]
|
||
- [[projects/bjd/references/bjd-wtb-hs-cross-reference-20260422]]
|
||
- [[projects/bjd/references/competitor-public-source-archive-20260605]]
|
||
"""
|
||
|
||
|
||
def write_pages(items: list[dict]) -> list[str]:
|
||
written = []
|
||
catalog_dir = VAULT / "_sources/catalog/bjd/competitors"
|
||
catalog_items = registry_competitor_items()
|
||
seen = {(i.get("brand"), i.get("name"), i.get("archive_path"), i.get("url")) for i in catalog_items}
|
||
for item in items:
|
||
key = (item.get("brand"), item.get("name"), item.get("archive_path"), item.get("url"))
|
||
if key not in seen:
|
||
catalog_items.append(item)
|
||
seen.add(key)
|
||
for vendor in sorted({i.get("brand") for i in catalog_items if i.get("brand")}):
|
||
path = catalog_dir / f"{vendor.lower()}.md"
|
||
path.write_text(vendor_catalog(vendor, catalog_items), encoding="utf-8")
|
||
written.append(str(path))
|
||
(catalog_dir / "index.md").write_text(index_catalog(catalog_items), encoding="utf-8")
|
||
written.append(str(catalog_dir / "index.md"))
|
||
pages = {
|
||
"projects/bjd/references/competitor-public-source-archive-20260605.md": master_page(items),
|
||
"projects/bjd/references/hirose-fh52-fh52k-public-sources-20260605.md": fh52_page(items),
|
||
"projects/bjd/references/te-2188698-73pin-hybrid-connector-public-sources-20260605.md": te_page(items),
|
||
"projects/bjd/references/iriso-public-competitor-sources-20260605.md": iriso_page(items),
|
||
}
|
||
for rel, body in pages.items():
|
||
path = VAULT / rel
|
||
path.write_text(body, encoding="utf-8")
|
||
written.append(str(path))
|
||
return written
|
||
|
||
|
||
def main() -> None:
|
||
items = load_results()
|
||
records = registry_records(items)
|
||
added = append_registry(records)
|
||
written = write_pages(items)
|
||
print(json.dumps({
|
||
"download_ok": sum(1 for i in items if i.get("ok")),
|
||
"download_fail": sum(1 for i in items if not i.get("ok")),
|
||
"registry_added": added,
|
||
"pages_written": written,
|
||
}, ensure_ascii=False, indent=2))
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main()
|