/** * 通用商品高级联动规则:用条件项限制结果项,并同步修正不再可选的表单值。 * 处理副本而非原始配置;无解、规则冲突或协议不完整时失败,不能返回看似合法的报价配置。 */ var e = (e) => (e && typeof e == `object` && !Array.isArray(e) ? e : {}), t = (t) => (Array.isArray(t) ? t.map(e) : []), n = (e) => JSON.parse(JSON.stringify(e)), r = (e) => [`quantity`, `quantity_range`].includes(String(e.option_type)), i = (e) => String(e.id ?? e.configoption_id ?? ``), a = (e) => (Array.isArray(e) ? e : [e]) .filter((e) => e != null && e !== ``) .map(Number), o = (e = `商品高级规则数据不完整`) => { throw Error(e); }; // 只执行 enabled 规则;每条必须有 condition/result,且 combine_mode 与 operator 已知。 function s(n) { return n == null ? [] : Array.isArray(n) ? n.flatMap((n) => { let r = e(n); if (![!0, 1, `1`].includes(r.enabled)) return []; [`all`, `any`].includes(String(r.combine_mode)) || o(); let i = t(r.terms).map( (e) => ( (![`condition`, `result`].includes(String(e.role)) || ![`in`, `not_in`].includes(String(e.operator)) || !Number.isSafeInteger(Number(e.configoption_id)) || Number(e.configoption_id) <= 0 || !t(e.values).length) && o(), { id: String(e.configoption_id), role: e.role, operator: e.operator, values: t(e.values), } ), ); return ( (!i.some((e) => e.role === `condition`) || !i.some((e) => e.role === `result`)) && o(), [ { mode: r.combine_mode, terms: i, }, ] ); }) : o(); } // 判断一个值是否命中规则:数量按闭区间比较,普通选项按正整数子项 id 比较。 function c(e, t, n) { return n.values.some((n) => { if (r(e)) return ( (n.qty_min === null || n.qty_min === void 0 || n.qty_max === null || n.qty_max === void 0 || !Number.isFinite(Number(n.qty_min)) || !Number.isFinite(Number(n.qty_max)) || Number(n.qty_max) < Number(n.qty_min)) && o(), t >= Number(n.qty_min) && t <= Number(n.qty_max) ); let i = Number(n.configoption_sub_id); return ((!Number.isSafeInteger(i) || i <= 0) && o(), t === i); }); } // in 条件任一值命中即可,in 结果要求全部已选值合法;not_in 则不能有任一命中。 function l(e, t, n) { let r = a(t).map((t) => c(e, t, n)); return n.operator === `not_in` ? !r.some(Boolean) : n.role === `condition` ? r.some(Boolean) : !!r.length && r.every(Boolean); } // 操作系统的实际可选 id 位于 version 层,不能把系统分类 id 当成镜像 id。 function u(e) { return e.option_type === `os` ? t(e.subs).flatMap((e) => t(e.version).map((e) => Number(e.id))) : t(e.subs).map((e) => Number(e.id)); } // 将实例既有配置转成规则可读的表单值;级联配置不参与普通项求值。 function d(e) { let n = {}; for (let o of e) { let e = i(o); if (!e || o.option_type === `cascade`) continue; let s = ( r(o) ? [Number(o.qty)] : o.configoption_sub_id === void 0 ? t(o.subs).some((e) => e.id !== void 0) ? t(o.subs).map((e) => Number(e.id)) : u(o) : [Number(o.configoption_sub_id)] ).filter(Number.isFinite); n[e] = r(o) || o.option_type === `multi_select` ? [...a(n[e]), ...s] : (s[0] ?? null); } return n; } /** 限制一个结果项:离散值过滤 subs,数量值按原始步长切分合法区间,而非枚举每个整数。 */ function f(e, n, i) { if ( (e.option_type === `cascade` && o(`高级规则不能将级联项作为普通配置提交`), !r(e)) ) { let r = (t) => n.operator === `not_in` ? !c(e, Number(t), n) : c(e, Number(t), n); e.subs = e.option_type === `os` ? t(e.subs) .map((e) => ({ ...e, version: t(e.version).filter((e) => r(e.id)), })) .filter((e) => e.version.length) : t(e.subs).filter((e) => r(e.id)); return; } let a = Number(i.qty_min ?? 0), s = Math.max(1, Number(i.qty_change || 1)); ((!Number.isSafeInteger(a) || !Number.isSafeInteger(s)) && o(), (e.subs = ( t(e.subs).length ? t(e.subs) : [ { qty_min: e.qty_min, qty_max: e.qty_max, }, ] ).flatMap((t) => { let r = a + Math.ceil((Number(t.qty_min) - a) / s) * s, i = a + Math.floor((Number(t.qty_max) - a) / s) * s; if (!Number.isSafeInteger(r) || !Number.isSafeInteger(i) || i < r) return []; // 用规则区间边界切段,保留相邻边界之间整段允许的数量,避免容量范围越大越慢。 let o = Math.floor((i - r) / s) + 1, l = [ ...new Set([ 0, o, ...n.values.flatMap( (t) => ( c(e, r, { ...n, values: [t], }), [ Math.ceil((Number(t.qty_min) - r) / s), Math.floor((Number(t.qty_max) - r) / s) + 1, ] ), ), ]), ] .filter((e) => e >= 0 && e <= o) .sort((e, t) => e - t); return l.slice(0, -1).flatMap((i, a) => { let o = r + i * s, u = r + (l[a + 1] - 1) * s, d = c(e, o, n); return u >= o && (n.operator === `not_in` ? !d : d) ? [ { ...t, qty_min: o, qty_max: u, }, ] : []; }); }))); let l = t(e.subs); l.length && ((e.qty_min = Math.min(...l.map((e) => Number(e.qty_min)))), (e.qty_max = Math.max(...l.map((e) => Number(e.qty_max))))); } // 选中值被规则排除时,回落到第一个合法值;无任何合法值时抛错,而非留下无效选择。 function p(e, n, s) { let c = i(e), l = String(e.option_name || c), d = n[c]; if (r(e)) { let r = t(e.subs), i = Number(s.qty_min ?? 0), u = Math.max(1, Number(s.qty_change || 1)); r.length || o(`${l}没有符合当前条件的配置`); let f = Number(r[0].qty_min), p = a(d).map((e) => r.some( (t) => e >= Number(t.qty_min) && e <= Number(t.qty_max) && (e - i) % u === 0, ) ? e : f, ); n[c] = Array.isArray(d) ? (p.length ? p : [f]) : (p[0] ?? f); } else { let t = u(e); if ( (t.length || o(`${l}没有符合当前条件的配置`), e.option_type === `multi_select`) ) { let e = a(d).filter((e) => t.includes(e)); n[c] = e.length ? e : [t[0]]; } else t.includes(Number(d)) || (n[c] = t[0]); } } /** * r/a/c/u 分别为可编辑选项、表单、原始规则和实例固定配置。 * 反复应用至表单稳定;重复状态表示循环冲突,固定配置不满足结果项时禁止继续。 */ function m(r, a, c, u = []) { let m = r.map((t) => n(e(t))), h = s(c); if (!h.length) return { options: r, form: a, }; let g = t(u), _ = new Map([...g, ...m].map((e) => [i(e), e])), v = d(g), y = n(a), b = new Set(); for (let e = 0; e <= m.length + h.length + 2; e++) { let e = JSON.stringify(y); (b.has(e) && o(`商品高级规则相互冲突,请重新选择配置`), b.add(e)); let t = n(m), r = { ...v, ...y, }, a = new Set(); for (let e of h) { let n = e.terms .filter((e) => e.role === `condition`) .map((e) => { let t = _.get(e.id); return t ? l(t, r[e.id], e) : null; }); if (e.mode === `any` ? n.some((e) => e === !0) : n.every((e) => e === !0)) for (let n of e.terms.filter((e) => e.role === `result`)) { let e = t.find((e) => i(e) === n.id); if (e) (f(e, n, _.get(n.id)), a.add(n.id)); else { let e = _.get(n.id); e && !l(e, r[n.id], n) && o(`所选配置与当前实例配置不兼容,请重新选择`); } } } for (let e of t) a.has(i(e)) && p(e, y, _.get(i(e))); if (JSON.stringify(y) === e) return { options: t, form: y, }; } return o(`商品高级规则无法确定,请重新选择配置`); } export { m as t };