Files
dusuniot/scripts/import-product-menu-order.ts
bigcode ddeeca3293 v0.10.21: 产品归档页 C1-C4(原站 /shop/ 模板 1398 + WPC 筛选 + WooCommerce 网格)
- 导入 archive 模板 post 1398(slug=shop-archive),/collection/ 用 ElementorRenderer
  直出 hero/两列外壳,按 widget id 注入 ShopFilters/ShopProducts;新增 server function
  解决客户端导航时 loader 打不开 db 的问题
- C1 hero:面包屑 Home / Shop(BreadcrumbWidget + vars.breadcrumb 上下文)
- C2 筛选:12 组属性(term taxonomy 顺序,scripts/import-attribute-term-order.ts);
  长期列表 5 项 + See more,Battery/Operating/Install 默认折叠;URL query 驱动,
  SoM 筛选实测 22 条;顶部 Filters 标题/已选 chips/Clear all
- C3 网格:WooCommerce 归档 DOM(结果计数、orderby、24 卡 4 列、卡片 1:1 图/标题/
  Read more);默认排序导入 products.meta.menu_order(scripts/import-product-menu-order.ts),
  前三个商品与原站一致(DSOM-040R/110R/130N)
- C4 分页:页码/箭头、当前页样式、page2 25–48 条验证
- 修复 Tailwind .columns-4 与 WooCommerce 网格类冲突;app.css 新增 shop 归档 scoped 样式
- 1436 实测:hero 52.8、shop 节 2906.7、筛选区 2798.7、网格 2523.3、卡 257.7×409、
  分页 y2855,与原站逐项一致(±6px 内);bun test 11 pass;版本 0.10.21
2026-11-02 12:32:18 +08:00

78 lines
2.6 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* # 脚本 导入产品 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();