v2.0: 4 分类真实数据替换 + 手册彩色重做 + 网页版改版

数据 (定位销/勾销缸/翻转缸/电缸 → Univer 真实数模)
- 新增 19 系列 1124 型号 (PIN 303 / HOK 73 / ROT 741 / ELEC 9)
- 命名规则取自官方图册 CODIFICATION KEY (pdftotext 提取), 非推测
- 解析用「官方值域校验 + 左对齐 DFS 填空」, 可处理省略空位的型号
- 参数组合唯一性门禁: 1124 型号全部通过 (避免选型静默错配)
- 占位/测试文件 (如 USP50J_0___K0 销径为空) 在解析阶段丢弃
- catalog.json 分类系列表同步; crossref 失效引用清理

手册页
- 全部 42 系列改为彩色 (此前脚本误写死 csGRAY 转灰度), 346 页
- 修复 UCBT 附图只有 1 页 (筛选条件写死 UCBT40 且漏 CLAMPING ARMS)
- gen-pending-series.py 改为扫描 manual 目录自动生成附件清单,
  避免重跑脚本把多页附件覆盖回单页

网页版
- 首页改为系列缩略图网格 (40 张: 27 张真实产品图 + 13 张占位图),
  按大类分组; 图放 web/series/<系列码>.webp, 覆盖同名文件即可替换
- 左侧树改手风琴 (默认收起, 一次展开一个), 父级带 SVG 图标,
  悬停放大动画, 按钮间距随高度均匀分布; 可收起为图标窄条
- 修复分隔条被拖出容器后无法找回 (上限改为容器感知 + resize 重夹取
  + 双击复位); 同时阻止图片原生拖拽
- 购物车打包改取 .step.gz 副档 (传输量降至约 1/4.5), 无副档自动回退
- 修复搜索到型号后点结果内容区空白 (switchTab('dim') 已失效)
- OpcPackage 超大包 (>1.5GB) 改走临时文件, 绕过 MemoryStream 2GB 上限

工具
- gen-pending-series/manual, copy-pending-step, gen-step-gz,
  gen-series-thumbs, scan-pending-series 等 11 个脚本

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
wangruiguo
2026-09-15 01:05:17 +08:00
parent 0584ba67b4
commit 3c4f236cba
483 changed files with 6520 additions and 201 deletions

View File

@@ -0,0 +1,93 @@
# -*- coding: utf-8 -*-
"""
为没有产品图的系列生成统一风格占位缩略图 (web/series/<系列码>.webp)。
背景: 首页系列缩略图网格需要每个系列一张图。bom-viewer 项目已有 27 张真实产品图
(来自 onebot251231 网站后台), 其余 13 个系列 (KC/M/MS/MAL/KS 等基础气缸 +
UFL/LAGP 老码系列) 暂无 → 生成占位图, 用户后续用真图覆盖同名文件即可。
风格对齐卡片: 浅灰底 (--gray-50 #f9fafb) + 青色系列码大字 (--primary-700 #0f766e)
+ "图片待补" 小字, 尺寸 500x450 (与 bom-viewer 产品图一致)。
用法: PYTHONUTF8=1 python gen-series-thumbs.py
"""
import os
from PIL import Image, ImageDraw, ImageFont
WEB_SERIES = r'D:/开发/OnebotCatalog/web/series'
# 需要占位的系列 (bom-viewer 里没有对应的产品图)
PLACEHOLDER = ['KC', 'KCB', 'KSB', 'KCS', 'KS', 'KSU',
'M', 'MS', 'MSC', 'MAL', 'MALC', 'UFL', 'LAGP']
W, H = 500, 450
BG = (249, 250, 251) # --gray-50
CODE_COLOR = (15, 118, 110) # --primary-700
SUB_COLOR = (156, 163, 175) # --gray-400
BOX = (229, 231, 235) # --gray-200
FONT_CANDIDATES = [
r'C:\Windows\Fonts\consolab.ttf', # Consolas Bold — 与卡片等宽字体一致
r'C:\Windows\Fonts\consola.ttf',
r'C:\Windows\Fonts\msyhbd.ttc',
]
CN_FONT_CANDIDATES = [
r'C:\Windows\Fonts\msyh.ttc',
r'C:\Windows\Fonts\msyhl.ttc',
]
def load_font(paths, size):
for p in paths:
if os.path.exists(p):
try:
return ImageFont.truetype(p, size)
except Exception:
continue
return ImageFont.load_default()
def make_one(code, out_path):
im = Image.new('RGB', (W, H), BG)
d = ImageDraw.Draw(im)
# 虚线圆角外框 (暗示"这里是图位")
d.rounded_rectangle([26, 26, W - 26, H - 26], radius=18, outline=BOX, width=2)
# 系列码大字 (居中)
f_code = load_font(FONT_CANDIDATES, 84)
bbox = d.textbbox((0, 0), code, font=f_code)
d.text(((W - (bbox[2] - bbox[0])) / 2 - bbox[0],
H / 2 - 62 - (bbox[3] - bbox[1]) / 2), code, font=f_code, fill=CODE_COLOR)
# 分隔短线
d.line([(W / 2 - 34, H / 2 + 8), (W / 2 + 34, H / 2 + 8)], fill=BOX, width=2)
# "图片待补" (中英各一行, 居中)
f_cn = load_font(CN_FONT_CANDIDATES, 20)
f_en = load_font(FONT_CANDIDATES, 15)
t1 = '图片待补'
b1 = d.textbbox((0, 0), t1, font=f_cn)
d.text(((W - (b1[2] - b1[0])) / 2 - b1[0], H / 2 + 30), t1, font=f_cn, fill=SUB_COLOR)
t2 = 'IMAGE PENDING'
b2 = d.textbbox((0, 0), t2, font=f_en)
d.text(((W - (b2[2] - b2[0])) / 2 - b2[0], H / 2 + 62), t2, font=f_en, fill=SUB_COLOR)
im.save(out_path, 'WEBP', quality=88, method=6)
return os.path.getsize(out_path)
def main():
os.makedirs(WEB_SERIES, exist_ok=True)
total = 0
for code in PLACEHOLDER:
p = os.path.join(WEB_SERIES, code + '.webp')
sz = make_one(code, p)
total += sz
print(f' {code:6s} -> {sz/1024:5.1f} KB')
print(f'\n生成 {len(PLACEHOLDER)} 张占位图, 共 {total/1024:.0f} KB')
print('替换方式: 用真图覆盖 web/series/<系列码>.webp 即可 (无需改代码)')
if __name__ == '__main__':
main()