# -*- coding: utf-8 -*- """一次性迁移:把 python 代理的 proxy_cache 展开成静态目录树 → bin\\Debug\\元件库网页\\ 数据平移,不带旧服务逻辑。规则: 1. price_standalone.html / jquery.min.js 直接拷到根 2. 关键资源按【页面引用清单 override】精确落位(解决键名下划线歧义) 3. electricData/privateJson/electricPic/privateImg 各取最大缓存 → 固定路径(查询忽略) 4. webGetPrice 族(dx2_pcprice..._hash) → dx2_webGetPrice\\ 原键保存(server.cjs 按 infoJson hash 查) 5. 其余键:下划线全展开为目录树,同类多版本保留最新 """ import os, re, shutil, sys ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) SRC = os.path.join(ROOT, "旧服务-python代理", "src") CACHE = os.path.join(SRC, "proxy_cache") PAGE_DIR = os.path.join(ROOT, "成套报价软件", "bin", "Debug", "元件库网页") OUT = os.path.join(PAGE_DIR, "data") # 迁移只重建 data\;server.cjs/页面 在外层不动 # 键名 → 精确目标路径(页面/SDK 实际请求;键不带 .data 后缀) OVERRIDE = { "dian_open_api_css_jprice_public.min.css": "dian/open/api/css/jprice_public.min.css", "open_api_css_jprice_public.min.css": "open/api/css/jprice_public.min.css", "open_api_css_jprice.min.css": "open/api/css/jprice.min.css", "dian_open_api_js_jprice-2.0.0.js": "dian/open/api/js/jprice-2.0.0.js", "viewer2_preview_ztree_zTreeStyle.css": "viewer2/preview/ztree/zTreeStyle.css", "viewer2_preview_ztree_preview.css": "viewer2/preview/ztree/preview.css", "open_api_images_zTreeStandard.png": "open/api/images/zTreeStandard.png", "images_nopic.png": "images/nopic.png", } def main(): if not os.path.isdir(CACHE): print("!! 找不到 proxy_cache:", CACHE); sys.exit(1) if os.path.isdir(OUT): shutil.rmtree(OUT) os.makedirs(OUT) # 1. 页面与 jquery(放外层,与 server.cjs 同级) for f in ("price_standalone.html", "jquery.min.js"): shutil.copy2(os.path.join(SRC, f), os.path.join(PAGE_DIR, f)) print("OK 页面+jquery") # 收集缓存键(去 .meta/.data,同名保留最新 mtime 的 .data) entries = {} # 键 -> (data路径, mtime, size) for name in os.listdir(CACHE): if not name.endswith(".data"): continue key = name[:-5] p = os.path.join(CACHE, name) st = os.stat(p) old = entries.get(key) if old is None or st.st_mtime > old[1]: entries[key] = (p, st.st_mtime, st.st_size) print("缓存键总数:", len(entries)) # 2. webGetPrice 族 → 独立目录原键保存 n_wgp = 0 os.makedirs(os.path.join(OUT, "dx2_webGetPrice"), exist_ok=True) for key, (p, _, _) in list(entries.items()): if "webGetPrice" in key: shutil.copy2(p, os.path.join(OUT, "dx2_webGetPrice", key + ".data")) entries.pop(key); n_wgp += 1 print("OK webGetPrice:", n_wgp) # 3. electricData 族:全部 ZIP 按内部文件名平移到 electricData_zips\(server.cjs 按 v 参数路由) import zipfile n_zip = 0 os.makedirs(os.path.join(OUT, "dian", "electricData_zips"), exist_ok=True) for key in list(entries.keys()): if "electricData" not in key: continue p = entries[key][0] try: z = zipfile.ZipFile(p) inner = z.namelist()[0] if z.namelist() else "" except Exception: inner = "" if not inner: continue base = inner[:-3] if inner.endswith(".js") else (inner[:-2] if inner.endswith("js") else inner) base = base.rstrip(".") dst = os.path.join(OUT, "dian", "electricData_zips", base + ".zip") if not os.path.exists(dst): shutil.copy2(p, dst) n_zip += 1 entries.pop(key) print("OK electricData ZIPs:", n_zip) # electricPic 等取最大一份 → 固定路径 for 词, 目标 in [("privateJson", ("dian", "privateJson")), ("electricPic", ("dian", "electricPic")), ("privateImg", ("dian", "privateImg"))]: best_key, best = None, None for key, (p, mt, sz) in entries.items(): base = key.rsplit("/", 1)[-1] 名 = base.split("_")[0] if "_" in base else base # 键形如 dian_electricData_xxxxxxxx / electricData parts = key.split("_") if 词 in parts or key == 词 or (parts and parts[0] == "dian" and len(parts) > 1 and parts[1].startswith(词)): if best is None or sz > best[2]: best_key, best = key, (p, mt, sz) if best: dst = os.path.join(OUT, *目标) os.makedirs(os.path.dirname(dst), exist_ok=True) shutil.copy2(best[0], dst) entries.pop(best_key) print("OK %s <- %s (%d B)" % (词, best_key, best[2])) else: print("!! %s 无缓存" % 词) # 4. override 精确落位 n_ov = 0 for key, rel in OVERRIDE.items(): if key in entries: dst = os.path.join(OUT, *rel.split("/")) os.makedirs(os.path.dirname(dst), exist_ok=True) shutil.copy2(entries[key][0], dst) entries.pop(key); n_ov += 1 else: # 有参数hash变体:找 键_hash cand = [k for k in entries if k == key or k.startswith(key + "_")] if cand: cand.sort(key=lambda k: -entries[k][2]) k0 = cand[0] dst = os.path.join(OUT, *rel.split("/")) os.makedirs(os.path.dirname(dst), exist_ok=True) shutil.copy2(entries[k0][0], dst) entries.pop(k0); n_ov += 1 else: print("!! override 缺缓存:", key) print("OK override:", n_ov) # 5. 其余全展开(下划线→斜杠);去掉 _参数hash 尾巴后仍带 8 位 hex 的整段保留 n_tree = 0 for key, (p, _, _) in entries.items(): rel = key.replace("_", "/") dst = os.path.join(OUT, *rel.split("/")) try: os.makedirs(os.path.dirname(dst), exist_ok=True) if os.path.exists(dst): os.remove(dst) shutil.copy2(p, dst) n_tree += 1 except OSError: pass # 非法文件名等跳过 print("OK 目录树:", n_tree) total = sum(len(fs) for _, _, fs in os.walk(OUT)) size = sum(os.path.getsize(os.path.join(r, f)) for r, _, fs in os.walk(OUT) for f in fs) print("完成: %d 文件, %.1f MB → %s" % (total, size / 1048576.0, OUT)) if __name__ == "__main__": main()