/** 购物车编辑的数据快照、并发校验与选中项恢复;所有比较以规范化的可提交字段为准。 */ // 合并原商品和编辑值,剔除展示字段,统一数量和可选配置的默认值。 function e(e, t = {}) { let n = { ...e, ...t, }; return { product_id: Number(n.product_id), config_options: n.config_options ?? {}, qty: Math.max(1, Number(n.qty ?? 1)), customfield: n.customfield ?? {}, self_defined_field: n.self_defined_field ?? {}, }; } // 隔离编辑页和列表页的可变对象;只用于接口提供的 JSON 数据。 function t(e) { return JSON.parse(JSON.stringify(e)); } function n(n) { return n.map((n) => t(e(n))); } // 递归排序对象键并省略 undefined,使相同内容不受属性插入顺序影响。 function r(e) { return Array.isArray(e) ? e.map(r) : e && typeof e == `object` ? Object.fromEntries( Object.entries(e) .filter(([, e]) => e !== void 0) .sort(([e], [t]) => e.localeCompare(t)) .map(([e, t]) => [e, r(t)]), ) : e; } function i(t) { return JSON.stringify(r(e(t))); } // 编辑期间后端若删除了已保存的自定义字段,不能静默丢字段继续保存。 function a(e, t) { if (!e) return; let n = e.item.self_defined_field ?? {}; if (Object.keys(n).some((e) => !t.includes(e))) throw Error(`商品自定义字段已调整,请返回购物车删除该项后重新配置`); } // 选中态只在内存中跨购物车/编辑页传递,不把商品配置长期写入浏览器存储。 var o = null; async function s(e) { let t = new TextEncoder().encode(i(e)); return Array.from( new Uint8Array(await crypto.subtle.digest(`SHA-256`, t)), (e) => e.toString(16).padStart(2, `0`), ).join(``); } /** 记录离开购物车前各项指纹与选中位置;SHA-256 用于内容匹配,不承担身份认证。 */ async function c(e, t) { let n = [...t]; o = { fingerprints: await Promise.all(e.map(s)), indices: n, }; } /** 一次性消费选中态;相同商品按其重复出现次序匹配,避免全部映射到同一位置。 */ async function l(e) { let t = o; if (!t) return null; o = null; let n = await Promise.all(e.map(s)), r = new Set(); return t.indices.flatMap((e) => { let i = t.fingerprints .slice(0, e) .filter((n) => n === t.fingerprints[e]).length, a = n.flatMap((n, r) => (n === t.fingerprints[e] ? [r] : []))[i]; return a === void 0 || r.has(a) ? [] : (r.add(a), [a]); }); } /** * n 为 API 客户端,r 包含 position/item;返回函数的第二参 u 检查报价是否仍有效。 * 保存前重取购物车并比较原始项,提交 expected_item 供后端进一步检测并发变更。 */ function u(n, r) { let a = r ? t(r.item) : null, c = !1; return async (l, u) => { if (!r || !a) throw Error(`购物车编辑上下文缺失`); if (c) throw Error(`正在保存,请勿重复操作`); c = !0; let d = t(e(a, l)); try { let c = (await n.get(`/cart`)).list?.[r.position]; if (!c || i(c) !== i(a)) throw Error(`购物车商品已变化,请返回购物车刷新后重新编辑`); if (!u()) throw Error(`配置已改变,请重新确认报价后保存`); let l = await n.put(`/cart/${r.position}`, { ...d, expected_item: e(a), }), f = a; a = t({ ...a, ...d, }); // 成功后同步指纹,返回购物车时仍能识别刚编辑过的选中商品。 let p = o; return ( p && p.fingerprints[r.position] === (await s(f)) && (p.fingerprints[r.position] = await s(a)), l ); } finally { c = !1; } }; } export { l as a, c as i, t as n, a as o, u as r, n as t };