/** * # 脚本 导入产品 menu_order(WooCommerce 默认排序依据) * 原站 /shop/ 默认排序 = wp_posts.menu_order ASC(取证:DSOM-040R=1、DSOM-110R=3、 * DSOM-130N=4,与线上商品顺序一致)。本项目 products 表无 menu_order 列, * 故写入 products.meta.menu_order,listProducts 默认排序读取该字段。 * 数据源:legacy dump 的 wp_posts 全部 INSERT 段(每段 23 字段,menu_order 为第 20 列)。 * 运行:bun scripts/import-product-menu-order.ts */ import { SQL } from "bun"; const DUMP = "/home/bigcode/data/dev/sites/dusuniot/legacy/dusuniot-db-20261029.sql"; const db = new SQL("postgres://dusuniot:dusuniot@127.0.0.1:25432/dusuniot"); /** # 函数 解析 SQL 值元组(仅支持字符串/数字,处理反斜杠转义与括号深度) */ function parseTuples(s: string, from: number): string[][] { const out: string[][] = []; let p = from; while (p < s.length) { if (s[p] === ";") break; if (s[p] !== "(") { p++; continue; } const values: string[] = []; let cur = ""; let inQ = false; let esc = false; let depth = 0; p++; for (; p < s.length; p++) { const ch = s[p]!; if (esc) { cur += ch; esc = false; continue; } if (inQ) { if (ch === "\\") { esc = true; continue; } if (ch === "'") { inQ = false; continue; } cur += ch; continue; } if (ch === "'") { inQ = true; continue; } if (ch === "(") { depth++; cur += ch; continue; } if (ch === ")") { if (depth === 0) { values.push(cur); cur = ""; p++; break; } depth--; cur += ch; continue; } if (ch === "," && depth === 0) { values.push(cur); cur = ""; continue; } cur += ch; } out.push(values); } return out; } const text = await Bun.file(DUMP).text(); const rows: string[][] = []; let idx = 0; while (true) { const i = text.indexOf("INSERT INTO `wp_posts`", idx); if (i < 0) break; const start = text.indexOf("(", i); rows.push(...parseTuples(text, start)); idx = text.indexOf(";", start); if (idx < 0) break; } const products = rows.filter((v) => v[20] === "product"); console.log("dump product rows:", products.length); let updated = 0; for (const v of products) { const legacyId = Number(v[0]); const order = Number(v[19] || 0); if (!legacyId) continue; const res = await db` UPDATE products SET meta = COALESCE(meta, '{}'::jsonb) || jsonb_build_object('menu_order', ${order}) WHERE legacy_id = ${legacyId}`; if (res.count) updated += res.count; } console.log("updated products:", updated); await db.end();