153 lines
6.6 KiB
Python
153 lines
6.6 KiB
Python
# -*- 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()
|