| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247 |
- # -*- coding: utf-8 -*-
- """Regenerate restore SQL: only current (status=0) image per mes_icons id."""
- from __future__ import print_function
- from collections import Counter, defaultdict
- import os
- import sys
- sys.path.insert(0, r"D:\IdeaProjects\mes-ahdy\mescloud\_apk_work")
- from extract_mes_icons_files import ( # noqa: E402
- DUMP,
- OUT_DIR,
- find_offsets,
- iter_value_rows,
- parse_create_columns,
- read_until_stmt_end,
- row_to_dict,
- sql_quote,
- unquote,
- )
- def pick_latest(lst):
- return sorted(
- lst,
- key=lambda x: (
- x.get("update_date") or "",
- x.get("create_date") or "",
- x.get("id") or "",
- ),
- reverse=True,
- )[0]
- def main():
- hits = find_offsets(DUMP, ["mes_icons", "js_sys_file_upload", "js_sys_file_entity"])
- create_cols = {}
- inserts = {}
- for off, name in hits:
- if name.startswith("CREATE:"):
- t = name.split(":", 1)[1]
- stmt = read_until_stmt_end(DUMP, off, max_bytes=200 * 1024)
- create_cols[t] = parse_create_columns(stmt)
- else:
- inserts[name] = off
- icons_cols = create_cols["mes_icons"]
- upload_cols = create_cols["js_sys_file_upload"]
- entity_cols = create_cols["js_sys_file_entity"]
- icons = [row_to_dict(f, icons_cols) for f in iter_value_rows(DUMP, inserts["mes_icons"])]
- icon_by_id = {i["id"]: i for i in icons}
- biz_type_idx = upload_cols.index("biz_type")
- icon_uploads = []
- for fields in iter_value_rows(DUMP, inserts["js_sys_file_upload"]):
- if unquote(fields[biz_type_idx]) == "mesIcons_image":
- icon_uploads.append(row_to_dict(fields, upload_cols))
- print("upload status:", Counter(u.get("status") for u in icon_uploads))
- by_biz = defaultdict(list)
- for u in icon_uploads:
- if (u.get("status") or "0") == "0":
- by_biz[u.get("biz_key")].append(u)
- current = {}
- for k, lst in by_biz.items():
- if k:
- current[k] = pick_latest(lst)
- print(
- "modules with active image=%d, multi-active=%d"
- % (len(current), sum(1 for v in by_biz.values() if len(v) > 1))
- )
- needed = set(u["file_id"] for u in current.values() if u.get("file_id"))
- file_id_idx = entity_cols.index("file_id")
- entities = {}
- for fields in iter_value_rows(DUMP, inserts["js_sys_file_entity"]):
- fid = unquote(fields[file_id_idx])
- if fid in needed:
- entities[fid] = row_to_dict(fields, entity_cols)
- if len(entities) == len(needed):
- break
- print("entities=%d" % len(entities))
- def disk_rel(e):
- if not e:
- return ""
- path = (e.get("file_path") or "").replace("\\", "/")
- md5 = e.get("file_md5") or ""
- ext = e.get("file_extension") or ""
- return ("%s%s.%s" % (path, md5, ext)) if ext else ("%s%s" % (path, md5))
- map2 = os.path.join(OUT_DIR, "mes_icons_image_map_current_only.txt")
- with open(map2, "w", encoding="utf-8") as wf:
- wf.write(
- "icon_id\ttitle\tmode\ticon_status\tupload_id\tfile_id\tfile_name\t"
- "file_path\tfile_md5\text\tdisk_rel\tupdate_date\n"
- )
- for biz_key in sorted(current.keys()):
- u = current[biz_key]
- e = entities.get(u.get("file_id") or {}, {})
- ic = icon_by_id.get(biz_key, {})
- wf.write(
- "\t".join(
- [
- biz_key,
- ic.get("title") or "",
- ic.get("mode") or "",
- ic.get("status") or "",
- u.get("id") or "",
- u.get("file_id") or "",
- u.get("file_name") or "",
- (e.get("file_path") or "").replace("\\", "/"),
- e.get("file_md5") or "",
- e.get("file_extension") or "",
- disk_rel(e),
- u.get("update_date") or "",
- ]
- )
- + "\n"
- )
- print("Wrote", map2)
- sql_path = os.path.join(OUT_DIR, "restore_mes_icons_image_mapping.sql")
- with open(sql_path, "w", encoding="utf-8") as wf:
- wf.write("-- ============================================================\n")
- wf.write("-- Restore PDA功能模块图片映射(仅当前有效图 status=0,每模块取最新一条)\n")
- wf.write("-- 来源: mes_cloud_20260919.sql\n")
- wf.write("-- 关联: biz_key=mes_icons.id, biz_type=mesIcons_image\n")
- wf.write("-- 务必同步拷贝磁盘文件到新服务器 {baseDir}/userfiles/\n")
- wf.write("-- ============================================================\n")
- wf.write("SET NAMES utf8mb4;\nSTART TRANSACTION;\n\n")
- wf.write("-- 1) 文件实体\n")
- for fid in sorted(needed):
- e = entities[fid]
- size = e.get("file_size")
- size_sql = size if size is not None else "NULL"
- wf.write(
- "INSERT INTO `js_sys_file_entity` "
- "(`file_id`,`file_md5`,`file_path`,`file_content_type`,`file_extension`,"
- "`file_size`,`file_meta`,`file_preview`) VALUES (%s,%s,%s,%s,%s,%s,%s,%s) "
- "ON DUPLICATE KEY UPDATE "
- "`file_md5`=VALUES(`file_md5`),`file_path`=VALUES(`file_path`),"
- "`file_content_type`=VALUES(`file_content_type`),"
- "`file_extension`=VALUES(`file_extension`),`file_size`=VALUES(`file_size`),"
- "`file_meta`=VALUES(`file_meta`),`file_preview`=VALUES(`file_preview`);\n"
- % (
- sql_quote(e.get("file_id")),
- sql_quote(e.get("file_md5")),
- sql_quote(e.get("file_path")),
- sql_quote(e.get("file_content_type")),
- sql_quote(e.get("file_extension")),
- size_sql,
- sql_quote(e.get("file_meta")),
- sql_quote(e.get("file_preview")),
- )
- )
- wf.write("\n-- 2) 按模块 id 替换绑定\n")
- for biz_key in sorted(current.keys()):
- u = current[biz_key]
- ic = icon_by_id.get(biz_key, {})
- e = entities.get(u.get("file_id") or {}, {})
- wf.write(
- "\n-- id=%s title=%s mode=%s disk=%s\n"
- % (biz_key, ic.get("title") or "", ic.get("mode") or "", disk_rel(e))
- )
- wf.write(
- "DELETE FROM `js_sys_file_upload` "
- "WHERE `biz_type`='mesIcons_image' AND `biz_key`=%s;\n"
- % sql_quote(biz_key)
- )
- sortv = u.get("file_sort")
- sort_sql = sortv if sortv is not None else "NULL"
- wf.write(
- "INSERT INTO `js_sys_file_upload` "
- "(`id`,`file_id`,`file_name`,`file_type`,`file_sort`,`biz_key`,`biz_type`,"
- "`status`,`create_by`,`create_date`,`update_by`,`update_date`,`remarks`) "
- "VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s);\n"
- % (
- sql_quote(u.get("id")),
- sql_quote(u.get("file_id")),
- sql_quote(u.get("file_name")),
- sql_quote(u.get("file_type")),
- sort_sql,
- sql_quote(u.get("biz_key")),
- sql_quote(u.get("biz_type")),
- sql_quote(u.get("status") or "0"),
- sql_quote(u.get("create_by") or "system"),
- sql_quote(u.get("create_date")),
- sql_quote(u.get("update_by") or "system"),
- sql_quote(u.get("update_date")),
- sql_quote(u.get("remarks")),
- )
- )
- missing = [
- i
- for i in icons
- if i.get("id") not in current and (i.get("status") or "0") == "0"
- ]
- if missing:
- wf.write("\n-- 老库正常模块但无有效图片:\n")
- for i in missing:
- wf.write(
- "-- id=%s title=%s mode=%s\n"
- % (i.get("id"), i.get("title"), i.get("mode"))
- )
- wf.write("\nCOMMIT;\n")
- wf.write(
- "\n-- 校验:\n"
- "-- SELECT u.biz_key, i.title, i.mode, u.file_name, e.file_path, e.file_md5, e.file_extension\n"
- "-- FROM js_sys_file_upload u\n"
- "-- LEFT JOIN js_sys_file_entity e ON e.file_id=u.file_id\n"
- "-- LEFT JOIN mes_icons i ON i.id=u.biz_key\n"
- "-- WHERE u.biz_type='mesIcons_image' AND u.status='0'\n"
- "-- ORDER BY i.title;\n"
- )
- print("Wrote", sql_path)
- files_list = os.path.join(OUT_DIR, "mes_icons_image_files_to_copy.txt")
- seen = set()
- with open(files_list, "w", encoding="utf-8") as wf:
- wf.write("# 拷到新服务器 {file.baseDir}/userfiles/ 下,保持相对路径\n")
- for u in current.values():
- rel = disk_rel(entities.get(u.get("file_id") or {}))
- if not rel or rel in seen:
- continue
- seen.add(rel)
- wf.write(rel + "\n")
- print("files=%d Wrote %s" % (len(seen), files_list))
- print("--- preview (first 15) ---")
- with open(map2, encoding="utf-8") as rf:
- for i, line in enumerate(rf):
- if i <= 15:
- print(line.rstrip())
- else:
- break
- print("DONE")
- if __name__ == "__main__":
- main()
|