2494 lines
140 KiB
Vue
2494 lines
140 KiB
Vue
<script>
|
||
/** 通用 idcsmart 商品配置:支持高级联动、多选、可重复数量项、级联树和操作系统分组。 */
|
||
import "~/assets/styles/ConfigDiskCard.Dx9IqqQ_.css";
|
||
import "~/assets/styles/PromoCodeField.qFEkB6Hm.css";
|
||
import "~/assets/styles/ProductCustomFields.B2QMnPil.css";
|
||
import "~/assets/styles/OsIcon.CAi4Iz2S.css";
|
||
import "~/assets/styles/CommonConfig.Cfik-oMe.css";
|
||
import { toDisplayString } from "vue";
|
||
import { renderList } from "vue";
|
||
import { onMounted } from "vue";
|
||
import { normalizeClass } from "vue";
|
||
import { onBeforeUnmount } from "vue";
|
||
import { renderSlot } from "vue";
|
||
import { watch } from "vue";
|
||
import { createBlock } from "vue";
|
||
import { ref } from "vue";
|
||
import { withCtx } from "vue";
|
||
import { createCommentVNode } from "vue";
|
||
import { createSlots } from "vue";
|
||
import { computed } from "vue";
|
||
import { isRef } from "vue";
|
||
import { createElementBlock } from "vue";
|
||
import { shallowRef } from "vue";
|
||
import { Fragment } from "vue";
|
||
import { createElementVNode } from "vue";
|
||
import { createTextVNode } from "vue";
|
||
import { unref } from "vue";
|
||
import { defineComponent } from "vue";
|
||
import { createVNode } from "vue";
|
||
import { openBlock } from "vue";
|
||
import { navigateTo } from "#app";
|
||
import { useApi } from "~/lib/auth.js";
|
||
import button from "primevue/button";
|
||
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
|
||
import message from "primevue/message";
|
||
import select from "primevue/select";
|
||
import inputnumber from "primevue/inputnumber";
|
||
import { t as os_name_t } from "~/lib/os-name.js";
|
||
import { r as configuration_display_r } from "~/lib/configuration-display.js";
|
||
import { t as configuration_display_t } from "~/lib/configuration-display.js";
|
||
import { i as product_fields_i } from "~/lib/product-fields.js";
|
||
import { r as product_fields_r } from "~/lib/product-fields.js";
|
||
import { t as product_fields_t } from "~/lib/product-fields.js";
|
||
import ConfigLoadingShell from "~/components/config/ConfigLoadingShell.vue";
|
||
import ConfigChoiceGrid from "~/components/config/ConfigChoiceGrid.vue";
|
||
import ProductCustomFields from "~/components/config/ProductCustomFields.vue";
|
||
import ConfigCheckout from "~/components/config/ConfigCheckout.vue";
|
||
import { n as cart_edit_n } from "~/lib/cart-edit.js";
|
||
import { o as cart_edit_o } from "~/lib/cart-edit.js";
|
||
import { r as cart_edit_r } from "~/lib/cart-edit.js";
|
||
import { t as common_advanced_rules_t } from "~/lib/common-advanced-rules.js";
|
||
import multiselect from "primevue/multiselect";
|
||
import ConfigDiskCard from "~/components/config/ConfigDiskCard.vue";
|
||
var ce = {
|
||
"1:month": `monthly`,
|
||
"3:month": `quarterly`,
|
||
"6:month": `semiannually`,
|
||
"12:month": `annually`,
|
||
"24:month": `biennially`,
|
||
"36:month": `triennially`,
|
||
};
|
||
// 默认值、购物车回填和界面共用可见叶子集合;隐藏祖先会隐藏整个子树。
|
||
// 保留后端遍历顺序供默认值使用,显示排序仅由界面处理。
|
||
function cascadeItems(option) {
|
||
const items = [];
|
||
function visit(nodes, path) {
|
||
for (const node of nodes) {
|
||
if (!node || typeof node !== `object` || Array.isArray(node)) continue;
|
||
if (Number(node.hidden) === 1) continue;
|
||
const name = String(node.item_name ?? ``).trim();
|
||
const labels = name ? [...path, name] : path;
|
||
const children = Array.isArray(node.children) ? node.children : [];
|
||
const id = Number(node.item_id);
|
||
if (
|
||
(Number(node.is_leaf) === 1 || children.length === 0) &&
|
||
Number.isInteger(id) &&
|
||
id > 0
|
||
)
|
||
items.push({ item_id: id, label: labels.join(` / `) || `选项 ${id}` });
|
||
else if (children.length) visit(children, labels);
|
||
}
|
||
}
|
||
visit(option.tree ?? [], []);
|
||
return items.filter(
|
||
(item, index) =>
|
||
items.findIndex((other) => other.item_id === item.item_id) === index,
|
||
);
|
||
}
|
||
function R(e, t = {}) {
|
||
// 业务状态按普通配置 u、级联 d、重复数量 p 分开存储,再按现有后端契约组装。
|
||
let n = useApi(),
|
||
r = t.edit,
|
||
a = ref(!r),
|
||
s = cart_edit_r(n, r),
|
||
l = shallowRef(null),
|
||
u = ref({}),
|
||
d = ref({}),
|
||
p = ref({}),
|
||
m = ref({}),
|
||
g = ref([]),
|
||
_ = ref(``),
|
||
v = ref(1),
|
||
y = ref(`—`),
|
||
b = ref(null),
|
||
x = ref(!0),
|
||
S = ref(!1),
|
||
C = ref(``),
|
||
T = computed(() => {
|
||
let e = l.value?.configoptions ?? [];
|
||
try {
|
||
return {
|
||
...common_advanced_rules_t(
|
||
e,
|
||
{
|
||
...u.value,
|
||
...p.value,
|
||
},
|
||
l.value?.advanced_rules,
|
||
),
|
||
error: ``,
|
||
};
|
||
} catch (t) {
|
||
return {
|
||
options: e,
|
||
form: {
|
||
...u.value,
|
||
...p.value,
|
||
},
|
||
error: t instanceof Error ? t.message : `商品高级规则无效`,
|
||
};
|
||
}
|
||
}),
|
||
E = computed(() => T.value.options),
|
||
D = !1;
|
||
function ee() {
|
||
// 高级规则可能修正多个关联值;D 防止同步深度 watch 在回写时递归执行同一轮规则。
|
||
if (D) return;
|
||
if (T.value.error) throw Error(T.value.error);
|
||
let e = T.value.form;
|
||
D = !0;
|
||
try {
|
||
for (let t of l.value?.configoptions ?? []) {
|
||
let n = String(t.id),
|
||
r = e[n];
|
||
if (r != null) {
|
||
if (
|
||
t.allow_repeat === 1 &&
|
||
[`quantity`, `quantity_range`].includes(t.option_type)
|
||
) {
|
||
let e = Array.isArray(r) ? r : [r];
|
||
(JSON.stringify(p.value[n]) !== JSON.stringify(e) &&
|
||
(p.value[n] = e),
|
||
(u.value[n] = e[0] ?? t.qty_min ?? 0));
|
||
} else
|
||
JSON.stringify(u.value[n]) !== JSON.stringify(r) &&
|
||
(u.value[n] = r);
|
||
}
|
||
}
|
||
} finally {
|
||
D = !1;
|
||
}
|
||
}
|
||
watch(
|
||
[u, p],
|
||
() => {
|
||
if (!(x.value || D))
|
||
try {
|
||
ee();
|
||
} catch (e) {
|
||
(L(),
|
||
(C.value = e instanceof Error ? e.message : `商品高级规则无效`));
|
||
}
|
||
},
|
||
{
|
||
deep: !0,
|
||
flush: `sync`,
|
||
},
|
||
);
|
||
let O = ref(``),
|
||
k = ref(0),
|
||
A = ref(0),
|
||
j = computed(() =>
|
||
JSON.stringify({
|
||
config: u.value,
|
||
cascade: d.value,
|
||
repeat: p.value,
|
||
cycle: _.value,
|
||
qty: v.value,
|
||
promo: O.value,
|
||
fields: m.value,
|
||
}),
|
||
),
|
||
ne = 0,
|
||
P = ref(``),
|
||
F = !1,
|
||
re = 0,
|
||
se = computed(
|
||
() =>
|
||
a.value &&
|
||
!T.value.error &&
|
||
!!P.value &&
|
||
P.value === j.value &&
|
||
!S.value,
|
||
);
|
||
function L() {
|
||
((ne += 1),
|
||
(P.value = ``),
|
||
(y.value = `—`),
|
||
(k.value = 0),
|
||
(A.value = 0),
|
||
(S.value = !1));
|
||
}
|
||
(watch(j, L, {
|
||
flush: `sync`,
|
||
}),
|
||
onBeforeUnmount(() => {
|
||
((F = !0), L());
|
||
}));
|
||
function R() {
|
||
if (F || !se.value)
|
||
throw Error(`当前配置报价尚未确认,请等待或重新计算报价`);
|
||
}
|
||
function le(e) {
|
||
if (e.option_type === `os`) return U(e)[0]?.versions[0]?.id;
|
||
if (e.option_type === `quantity` || e.option_type === `quantity_range`)
|
||
return e.qty_min ?? 1;
|
||
if (e.option_type === `multi_select`) {
|
||
let t = e.subs?.[0]?.id;
|
||
return t ? [t] : [];
|
||
}
|
||
return e.subs?.[0]?.id;
|
||
}
|
||
function ue() {
|
||
// 只初始化可显示配置,按字段类型选择默认值;免费/一次性/后付费周期使用协议关键字。
|
||
let e = l.value;
|
||
if (!e) return;
|
||
let t = {};
|
||
for (let n of e.configoptions) {
|
||
if (n.is_show !== 1) continue;
|
||
let e = le(n);
|
||
if (
|
||
(e !== void 0 && (t[String(n.id)] = e),
|
||
(n.option_type === `quantity` || n.option_type === `quantity_range`) &&
|
||
n.allow_repeat === 1 &&
|
||
(p.value[String(n.id)] = [Number(e ?? n.qty_min ?? 1)]),
|
||
n.option_type === `cascade`)
|
||
) {
|
||
let e = cascadeItems(n)[0];
|
||
e &&
|
||
(d.value[String(n.id)] = {
|
||
item_id: e.item_id,
|
||
quantity: 1,
|
||
});
|
||
}
|
||
}
|
||
u.value = t;
|
||
let n = e.custom_cycles ?? [],
|
||
r = n.find((e) => e.is_default === 1) ?? n[0],
|
||
i = e.common_product?.pay_type;
|
||
_.value =
|
||
i === `free` || i === `onetime` || i === `recurring_postpaid`
|
||
? i
|
||
: (r?.id ?? ``);
|
||
}
|
||
let de = computed(() => {
|
||
let e = l.value?.common_product?.pay_type,
|
||
t = {
|
||
free: `免费`,
|
||
onetime: `一次性`,
|
||
recurring_postpaid: `按需计费`,
|
||
};
|
||
return e && t[e]
|
||
? [
|
||
{
|
||
value: e,
|
||
label: t[e],
|
||
},
|
||
]
|
||
: (l.value?.custom_cycles ?? []).map((e) => ({
|
||
value: e.id,
|
||
label: e.name,
|
||
}));
|
||
}),
|
||
z = computed(() => {
|
||
let e = (l.value?.custom_cycles ?? []).find((e) => e.id === _.value),
|
||
t = l.value?.common_product?.pay_type;
|
||
if (t === `free` || t === `onetime` || t === `recurring_postpaid`)
|
||
return t;
|
||
if (!e) return ``;
|
||
let n = l.value?.cycles ?? {};
|
||
return (
|
||
n[String(e.id)] ||
|
||
n[`${e.cycle_time}:${e.cycle_unit}`] ||
|
||
(typeof t == `string` ? ce[`${e.cycle_time}:${e.cycle_unit}`] : ``) ||
|
||
e.id
|
||
);
|
||
});
|
||
function pe(e, t, n = 1) {
|
||
let r = l.value?.configoptions.find((t) => t.id === e);
|
||
r &&
|
||
r.option_type === `cascade` &&
|
||
cascadeItems(r).some((e) => e.item_id === t) &&
|
||
((d.value[String(e)] = {
|
||
item_id: t,
|
||
quantity: Math.max(1, Number(n) || 1),
|
||
}),
|
||
H());
|
||
}
|
||
function me(e) {
|
||
let t = l.value?.configoptions.find((t) => t.id === e);
|
||
if (!t || t.allow_repeat !== 1) return !1;
|
||
let n = p.value[String(e)] ?? [Number(t.qty_min || 1)];
|
||
return n.length >= Math.max(1, Number(t.max_repeat || 1))
|
||
? !1
|
||
: ((p.value[String(e)] = [...n, Number(t.qty_min || 1)]), H(), !0);
|
||
}
|
||
function he(e, t) {
|
||
let n = p.value[String(e)] ?? [];
|
||
return n.length <= 1 || t < 0 || t >= n.length
|
||
? !1
|
||
: ((p.value[String(e)] = n.filter((e, n) => n !== t)), H(), !0);
|
||
}
|
||
function B() {
|
||
// 可重复数量项必须按数组提交,普通项保持原值类型,不能把所有配置都转换成字符串。
|
||
let e = {};
|
||
for (let t of l.value?.configoptions ?? []) {
|
||
let n = u.value[String(t.id)];
|
||
if (n !== void 0) {
|
||
if (
|
||
(t.option_type === `quantity` ||
|
||
t.option_type === `quantity_range`) &&
|
||
t.allow_repeat === 1
|
||
) {
|
||
let r = (p.value[String(t.id)] ?? [])
|
||
.map((e) => Number(e))
|
||
.filter((e) => Number.isFinite(e));
|
||
e[String(t.id)] = r.length ? r : [Number(n)];
|
||
} else e[String(t.id)] = n;
|
||
}
|
||
}
|
||
return e;
|
||
}
|
||
function V() {
|
||
return Object.fromEntries(
|
||
Object.entries(d.value).map(([e, t]) => [
|
||
e,
|
||
{
|
||
item_id: t.item_id,
|
||
quantity: t.quantity,
|
||
},
|
||
]),
|
||
);
|
||
}
|
||
function ge() {
|
||
product_fields_i(g.value, m.value);
|
||
}
|
||
function _e(e) {
|
||
let t =
|
||
e.config_options &&
|
||
typeof e.config_options == `object` &&
|
||
!Array.isArray(e.config_options)
|
||
? cart_edit_n(e.config_options)
|
||
: {},
|
||
n =
|
||
t.configoption &&
|
||
typeof t.configoption == `object` &&
|
||
!Array.isArray(t.configoption)
|
||
? t.configoption
|
||
: {};
|
||
for (let e of l.value?.configoptions ?? []) {
|
||
let t = String(e.id);
|
||
if (!(t in n)) continue;
|
||
let r = n[t];
|
||
if (Array.isArray(r)) {
|
||
let n = r.map((e) => Number(e)).filter(Number.isFinite);
|
||
e.allow_repeat === 1 &&
|
||
(e.option_type === `quantity` || e.option_type === `quantity_range`)
|
||
? ((p.value[t] = n.length ? n : [Number(e.qty_min ?? 1)]),
|
||
(u.value[t] = p.value[t][0] ?? Number(e.qty_min ?? 1)))
|
||
: (u.value[t] = n);
|
||
} else
|
||
Number.isFinite(Number(r)) &&
|
||
((u.value[t] = Number(r)),
|
||
e.allow_repeat === 1 &&
|
||
(e.option_type === `quantity` ||
|
||
e.option_type === `quantity_range`) &&
|
||
(p.value[t] = [Number(r)]));
|
||
}
|
||
let r = t.cascade_configoption;
|
||
r &&
|
||
typeof r == `object` &&
|
||
!Array.isArray(r) &&
|
||
(d.value = Object.fromEntries(
|
||
Object.entries(r).flatMap(([e, t]) => {
|
||
if (!t || typeof t != `object` || Array.isArray(t)) return [];
|
||
let n = t,
|
||
r = Number(n.item_id),
|
||
i = Number(n.quantity ?? 1);
|
||
const option = l.value?.configoptions.find(
|
||
(option) => String(option.id) === e,
|
||
);
|
||
// 已保存的级联项不可静默替换成另一资源,也不能继续提交已隐藏的节点。
|
||
if (
|
||
!option ||
|
||
option.option_type !== `cascade` ||
|
||
!cascadeItems(option).some((item) => item.item_id === r)
|
||
)
|
||
throw Error(`商品级联配置已调整,请返回购物车删除该项后重新配置`);
|
||
return [
|
||
[
|
||
e,
|
||
{
|
||
item_id: r,
|
||
quantity: Math.max(1, Number.isFinite(i) ? i : 1),
|
||
},
|
||
],
|
||
];
|
||
}),
|
||
));
|
||
let i = t.repeat_configoption;
|
||
i &&
|
||
typeof i == `object` &&
|
||
!Array.isArray(i) &&
|
||
(p.value = Object.fromEntries(
|
||
Object.entries(i).map(([e, t]) => [
|
||
e,
|
||
Array.isArray(t) ? t.map(Number).filter(Number.isFinite) : [],
|
||
]),
|
||
));
|
||
let a = t.cycle ?? t.billing_cycle;
|
||
if (a !== void 0) {
|
||
let e = String(a),
|
||
t = (l.value?.custom_cycles ?? []).find((t) => {
|
||
let n =
|
||
l.value?.cycles?.[String(t.id)] ||
|
||
l.value?.cycles?.[`${t.cycle_time}:${t.cycle_unit}`] ||
|
||
ce[`${t.cycle_time}:${t.cycle_unit}`] ||
|
||
t.id;
|
||
return String(n) === e || String(t.id) === e;
|
||
});
|
||
t && (_.value = t.id);
|
||
}
|
||
let o = Number(e.qty);
|
||
Number.isInteger(o) && o > 0 && (v.value = o);
|
||
let s =
|
||
e.customfield &&
|
||
typeof e.customfield == `object` &&
|
||
!Array.isArray(e.customfield)
|
||
? e.customfield
|
||
: {},
|
||
c = t.promo_code ?? s.promo_code;
|
||
Array.isArray(c)
|
||
? (O.value = String(c.find(Boolean) ?? ``))
|
||
: c != null && (O.value = String(c));
|
||
let f =
|
||
e.self_defined_field &&
|
||
typeof e.self_defined_field == `object` &&
|
||
!Array.isArray(e.self_defined_field)
|
||
? e.self_defined_field
|
||
: {};
|
||
for (let e of g.value) m.value[e.id] = String(f[e.id] ?? ``);
|
||
}
|
||
async function H() {
|
||
// 先应用高级规则,再请求报价;请求序号与输入快照共同防止旧报价覆盖新配置。
|
||
if ((L(), F || !a.value || !l.value || !z.value)) return;
|
||
try {
|
||
ee();
|
||
} catch (e) {
|
||
C.value = e instanceof Error ? e.message : `商品高级规则无效`;
|
||
return;
|
||
}
|
||
let t = ++ne,
|
||
r = j.value,
|
||
i = () => !F && t === ne && r === j.value;
|
||
((S.value = !0), (C.value = ``));
|
||
try {
|
||
let t = await n.post(`/product/${e}/config_option`, {
|
||
id: e,
|
||
config_options: {
|
||
configoption: B(),
|
||
cascade_configoption: V(),
|
||
cycle: z.value,
|
||
promo_code: O.value,
|
||
event_promotion: ``,
|
||
},
|
||
qty: v.value,
|
||
});
|
||
if (!i()) return;
|
||
let a = t?.price_total ?? t?.price;
|
||
if (
|
||
a == null ||
|
||
String(a).trim() === `` ||
|
||
!Number.isFinite(Number(a)) ||
|
||
Number(a) < 0
|
||
)
|
||
throw Error(`未获得有效报价,请重新计算`);
|
||
((y.value = String(a)),
|
||
(k.value = Number(t?.price_promo_code_discount ?? 0)),
|
||
(A.value = Number(t?.price_client_level_discount ?? 0)),
|
||
(P.value = r),
|
||
(b.value = t?.preview ?? null));
|
||
} catch (e) {
|
||
if (!i()) return;
|
||
C.value = e instanceof Error ? e.message : `报价加载失败,请重试`;
|
||
} finally {
|
||
i() && (S.value = !1);
|
||
}
|
||
}
|
||
async function ve() {
|
||
// 重读商品配置后初始化默认值、校验并回填购物车,最终才开放报价与提交。
|
||
a.value = !1;
|
||
let i = ++re,
|
||
o = () => !F && i === re;
|
||
(L(), (x.value = !0), (C.value = ``));
|
||
try {
|
||
let i = await n.get(`/idcsmart_common/product/${e}/configoption`);
|
||
if (!o()) return;
|
||
if (
|
||
((l.value = i), (g.value = []), (m.value = {}), t.customFields || r)
|
||
) {
|
||
let t = await n.get(`/product/${e}/self_defined_field/order_page`);
|
||
if (!o()) return;
|
||
if (!Array.isArray(t?.data))
|
||
throw Error(`商品自定义字段加载失败,请重试`);
|
||
((g.value = product_fields_r(t)),
|
||
(m.value = product_fields_t(g.value)));
|
||
}
|
||
((d.value = {}),
|
||
(p.value = {}),
|
||
ue(),
|
||
cart_edit_o(
|
||
r,
|
||
g.value.map((e) => e.id),
|
||
),
|
||
r && _e(r.item),
|
||
(a.value = !0),
|
||
(x.value = !1),
|
||
await H());
|
||
} catch (e) {
|
||
o() &&
|
||
((l.value = null),
|
||
(C.value = e instanceof Error ? e.message : `加载商品配置失败`));
|
||
} finally {
|
||
o() && (x.value = !1);
|
||
}
|
||
}
|
||
function ye(e, t) {
|
||
return U(e).find((e) => e.name === t)?.versions ?? [];
|
||
}
|
||
function U(e) {
|
||
// 将供应商不同写法的系统名称归入显示分组,版本 ID 去重但仍保留原 ID 提交。
|
||
let t = [
|
||
[/^cent\s*os(?=$|[\s\d._-])/i, `CentOS`],
|
||
[/^debian(?=$|[\s\d._-])/i, `Debian`],
|
||
[/^ubuntu(?=$|[\s\d._-])/i, `Ubuntu`],
|
||
[/^windows(?=$|[\s\d._-])/i, `Windows`],
|
||
[/^rocky(?:[\s_-]*linux)?(?=$|[\s\d._-])/i, `Rocky Linux`],
|
||
[/^alma(?:[\s_-]*linux)?(?=$|[\s\d._-])/i, `AlmaLinux`],
|
||
[/^(?:fedora|fedroa)(?=$|[\s\d._-])/i, `Fedora`],
|
||
[/^freebsd(?=$|[\s\d._-])/i, `FreeBSD`],
|
||
[/^(?:vmware[\s_-]*)?esxi(?=$|[\s\d._-])/i, `ESXi`],
|
||
[/^open\s*suse(?=$|[\s\d._-])/i, `openSUSE`],
|
||
[/^alpine(?:[\s_-]*linux)?(?=$|[\s\d._-])/i, `Alpine Linux`],
|
||
[/^(?:red[\s_-]*hat|rhel)(?=$|[\s\d._-])/i, `Red Hat`],
|
||
],
|
||
n = new Map(),
|
||
r = new Set();
|
||
for (let i of e.subs ?? [])
|
||
for (let e of i.version ?? []) {
|
||
if (r.has(e.id)) continue;
|
||
let a = i.os?.trim() || e.option_name.trim() || `其他系统`,
|
||
o = t.find(([e]) => e.test(a))?.[1] ?? a,
|
||
s = n.get(o);
|
||
(s ||
|
||
((s = {
|
||
name: o,
|
||
versions: [],
|
||
}),
|
||
n.set(o, s)),
|
||
s.versions.push(e),
|
||
r.add(e.id));
|
||
}
|
||
return [...n.values()];
|
||
}
|
||
async function be() {
|
||
// 加购/编辑前确认报价与自定义字段;级联项按 item_id + quantity 独立提交。
|
||
(R(), ge());
|
||
let t = {
|
||
product_id: e,
|
||
config_options: {
|
||
configoption: B(),
|
||
cascade_configoption: V(),
|
||
cycle: z.value,
|
||
},
|
||
qty: v.value,
|
||
customfield: {
|
||
promo_code: O.value,
|
||
event_promotion: ``,
|
||
},
|
||
self_defined_field: {
|
||
...m.value,
|
||
},
|
||
};
|
||
if (r) {
|
||
let e = j.value;
|
||
return s(t, () => !F && se.value && e === j.value);
|
||
}
|
||
return n.post(`/cart`, t);
|
||
}
|
||
async function xe() {
|
||
if (r) throw Error(`请先保存配置,再返回购物车结算`);
|
||
return (
|
||
R(),
|
||
ge(),
|
||
n.post(`/product/settle`, {
|
||
product_id: e,
|
||
config_options: {
|
||
configoption: B(),
|
||
cascade_configoption: V(),
|
||
cycle: z.value,
|
||
promo_code: O.value,
|
||
event_promotion: ``,
|
||
},
|
||
qty: v.value,
|
||
self_defined_field: {
|
||
...m.value,
|
||
},
|
||
})
|
||
);
|
||
}
|
||
return {
|
||
data: l,
|
||
availableOptions: E,
|
||
configForm: u,
|
||
cycle: _,
|
||
cycleOptions: de,
|
||
selectedCycleKeyword: z,
|
||
cascadeConfig: d,
|
||
repeatedConfig: p,
|
||
selectCascade: pe,
|
||
addRepeat: me,
|
||
removeRepeat: he,
|
||
customFields: m,
|
||
customFieldDefinitions: g,
|
||
qty: v,
|
||
price: y,
|
||
promoCode: O,
|
||
promoDiscount: k,
|
||
levelDiscount: A,
|
||
preview: b,
|
||
loading: x,
|
||
priceLoading: S,
|
||
quoteReady: se,
|
||
error: C,
|
||
init: ve,
|
||
calcPrice: H,
|
||
osGroups: U,
|
||
osVersions: ye,
|
||
addToCart: be,
|
||
buyNow: xe,
|
||
};
|
||
}
|
||
var le = {
|
||
class: `config-page`,
|
||
},
|
||
ue = {
|
||
key: 1,
|
||
class: `panel config-load-error`,
|
||
},
|
||
de = {
|
||
key: 2,
|
||
class: `config-layout`,
|
||
},
|
||
z = {
|
||
class: `config-options`,
|
||
},
|
||
fe = {
|
||
class: `section-title`,
|
||
},
|
||
pe = {
|
||
class: `form-row`,
|
||
},
|
||
me = {
|
||
class: `form-row`,
|
||
},
|
||
he = {
|
||
key: 2,
|
||
class: `form-row`,
|
||
},
|
||
B = {
|
||
key: 3,
|
||
class: `form-row`,
|
||
},
|
||
V = {
|
||
class: `cascade-controls`,
|
||
},
|
||
ge = {
|
||
key: 0,
|
||
class: `hint`,
|
||
},
|
||
_e = {
|
||
key: 1,
|
||
class: `hint`,
|
||
},
|
||
H = {
|
||
key: 4,
|
||
class: `form-row`,
|
||
},
|
||
ve = {
|
||
key: 0,
|
||
class: `repeat-controls`,
|
||
},
|
||
ye = {
|
||
class: `repeat-label`,
|
||
},
|
||
U = {
|
||
key: 2,
|
||
class: `hint`,
|
||
},
|
||
be = {
|
||
key: 5,
|
||
class: `form-row`,
|
||
},
|
||
xe = {
|
||
key: 0,
|
||
class: `hint`,
|
||
},
|
||
Se = {
|
||
class: `form-row checkout-cycle`,
|
||
},
|
||
Ce = {
|
||
key: 0,
|
||
class: `form-row checkout-quantity`,
|
||
},
|
||
we = Object.assign(
|
||
_plugin_vue_export_helper_t(
|
||
defineComponent({
|
||
__name: `CommonConfig`,
|
||
props: {
|
||
productId: {},
|
||
identityLocked: {
|
||
type: Boolean,
|
||
},
|
||
edit: {},
|
||
},
|
||
emits: [`settled`],
|
||
setup(o, { emit: h }) {
|
||
let b = o,
|
||
w = h,
|
||
E = R(b.productId, {
|
||
customFields: !0,
|
||
edit: b.edit,
|
||
}),
|
||
{
|
||
data: M,
|
||
configForm: N,
|
||
cycle: te,
|
||
cycleOptions: ie,
|
||
selectedCycleKeyword: ae,
|
||
qty: I,
|
||
price: oe,
|
||
loading: ce,
|
||
priceLoading: we,
|
||
error: Te,
|
||
quoteReady: Ee,
|
||
cascadeConfig: De,
|
||
repeatedConfig: Oe,
|
||
promoCode: ke,
|
||
promoDiscount: Ae,
|
||
levelDiscount: je,
|
||
customFields: Me,
|
||
customFieldDefinitions: Ne,
|
||
} = E,
|
||
W = ref(null),
|
||
G = computed(() => !!b.identityLocked || W.value !== null),
|
||
K = ref(``),
|
||
q = ref(``),
|
||
Pe;
|
||
onBeforeUnmount(() => clearTimeout(Pe));
|
||
let Fe = computed(() => Ee.value && !G.value && !!ae.value),
|
||
Ie = computed(() =>
|
||
(
|
||
E.availableOptions?.value ??
|
||
M.value?.configoptions ??
|
||
[]
|
||
).filter((e) => e.is_show === 1),
|
||
),
|
||
J = computed(
|
||
() =>
|
||
new Map(
|
||
Ie.value
|
||
.filter((e) => e.option_type === `os`)
|
||
.map((e) => [e.id, E.osGroups(e)]),
|
||
),
|
||
),
|
||
Le = (e) =>
|
||
e.option_type === `area` ||
|
||
/区域|地区|地域|城市|机房|线路|数据中心/.test(e.option_name),
|
||
Y = (e) => configuration_display_t(e.option_name, e.option_type),
|
||
X = (e, t) =>
|
||
[`操作系统`, `镜像版本`].includes(Y(e))
|
||
? os_name_t(t)
|
||
: Y(e) === `网络类型`
|
||
? configuration_display_r(t)
|
||
: t;
|
||
function Z(e) {
|
||
return cascadeItems(e).sort((e, t) =>
|
||
e.label.localeCompare(t.label, `zh-Hans-CN`),
|
||
);
|
||
}
|
||
function Re(e) {
|
||
return De.value[String(e.id)]?.item_id ?? Z(e)[0]?.item_id ?? null;
|
||
}
|
||
function ze(e, t) {
|
||
let n = Number(t);
|
||
if (!Number.isInteger(n)) return;
|
||
let r = De.value[String(e.id)]?.quantity ?? 1;
|
||
E.selectCascade(e.id, n, r);
|
||
}
|
||
function Be(e) {
|
||
return De.value[String(e.id)]?.quantity ?? 1;
|
||
}
|
||
function Ve(e, t) {
|
||
let n = Re(e);
|
||
n !== null && E.selectCascade(e.id, n, Number(t) || 1);
|
||
}
|
||
function Q(e) {
|
||
let t = Oe.value[String(e.id)];
|
||
return t?.length
|
||
? t
|
||
: [Number(N.value[String(e.id)] ?? e.qty_min ?? 1)];
|
||
}
|
||
function He(e, t, n) {
|
||
let r = Number(n);
|
||
if (!Number.isFinite(r)) return;
|
||
let i = [...Q(e)];
|
||
((i[t] = Math.max(
|
||
Number(e.qty_min ?? 1),
|
||
Math.min(Number(e.qty_max || 2 ** 53 - 1), r),
|
||
)),
|
||
(Oe.value[String(e.id)] = i),
|
||
(N.value[String(e.id)] = i[0] ?? i[t]),
|
||
E.calcPrice());
|
||
}
|
||
let Ue = (e) => We(e) === `存储配置`;
|
||
function We(e) {
|
||
return e.option_type === `os`
|
||
? `操作系统`
|
||
: Le(e)
|
||
? `基础配置`
|
||
: /硬盘|磁盘|系统盘|数据盘|存储/.test(e.option_name)
|
||
? `存储配置`
|
||
: /带宽|流量|防御|防护|网络|IP|ipv[46]/i.test(e.option_name)
|
||
? `网络配置`
|
||
: `基础配置`;
|
||
}
|
||
let Ge = computed(() =>
|
||
[`基础配置`, `存储配置`, `网络配置`, `操作系统`]
|
||
.map((e) => ({
|
||
title: e,
|
||
options: Ie.value.filter((t) => We(t) === e),
|
||
}))
|
||
.filter((e) => e.options.length),
|
||
);
|
||
function Ke(e) {
|
||
let t = /^(?:([kmgtpe])(?:i?b)?|b)$/i.exec((e ?? ``).trim());
|
||
return t
|
||
? /ib$/i.test(e.trim())
|
||
? `${t[1].toUpperCase()}iB`
|
||
: t[1]
|
||
? `${t[1].toUpperCase()}B`
|
||
: `B`
|
||
: ``;
|
||
}
|
||
function qe(e, t = ``) {
|
||
let n =
|
||
/^(?:(NVMe|SSD|HDD|SAS|SATA)\s*)?(\d+(?:\.\d+)?)\s*([kmgtpe](?:i?b)?|b)?(?:\s*(NVMe|SSD|HDD|SAS|SATA))?$/i.exec(
|
||
e.trim(),
|
||
),
|
||
r = n && Ke(n[3] || t);
|
||
return !n || !r
|
||
? null
|
||
: {
|
||
size: Number(n[2]),
|
||
unit: r,
|
||
type: n[1] || n[4] || ``,
|
||
};
|
||
}
|
||
function $(e) {
|
||
// 只有能无歧义解析容量/单位的存储选项才转换成容量控件,其余保留显式选项选择。
|
||
if (
|
||
e.option_type === `quantity` ||
|
||
e.option_type === `quantity_range`
|
||
) {
|
||
let t =
|
||
Ke(e.unit) ||
|
||
(!e.unit?.trim() &&
|
||
/系统盘|数据盘|磁盘|硬盘|存储/.test(e.option_name) &&
|
||
!/数量|个数|块数|盘数/.test(e.option_name)
|
||
? `GB`
|
||
: ``),
|
||
n = Number(e.qty_min ?? 0),
|
||
r = Number(e.qty_max),
|
||
i = Number(e.qty_change) > 0 ? Number(e.qty_change) : 1;
|
||
if (
|
||
!t ||
|
||
!Number.isFinite(n) ||
|
||
!Number.isFinite(r) ||
|
||
n < 0 ||
|
||
r < n
|
||
)
|
||
return null;
|
||
let a = (e.subs ?? []).filter(
|
||
(e) =>
|
||
Number.isFinite(Number(e.qty_min)) &&
|
||
Number.isFinite(Number(e.qty_max)),
|
||
),
|
||
o = (
|
||
a.length
|
||
? a
|
||
: [
|
||
{
|
||
qty_min: n,
|
||
qty_max: r,
|
||
},
|
||
]
|
||
)
|
||
.map((e) => ({
|
||
type: `step`,
|
||
min_value:
|
||
n +
|
||
Math.ceil((Math.max(n, Number(e.qty_min)) - n) / i) * i,
|
||
max_value:
|
||
n +
|
||
Math.floor((Math.min(r, Number(e.qty_max)) - n) / i) * i,
|
||
step: i,
|
||
}))
|
||
.filter((e) => e.min_value <= e.max_value);
|
||
return o.length
|
||
? {
|
||
unit: t,
|
||
options: o,
|
||
presets: null,
|
||
selected: null,
|
||
choices: !1,
|
||
}
|
||
: null;
|
||
}
|
||
if (e.option_type !== `select`) return null;
|
||
let t = (e.subs ?? []).map((t) => ({
|
||
id: t.id,
|
||
capacity: qe(t.option_name, e.unit),
|
||
})),
|
||
n = t.find((t) => t.id === N.value[String(e.id)])?.capacity;
|
||
if (!n) return null;
|
||
let r = t.every((e) => e.capacity?.unit === n.unit),
|
||
i = new Set(t.map((e) => e.capacity?.size)).size === t.length,
|
||
a = t.every(
|
||
(e) => e.capacity?.type.toUpperCase() === n.type.toUpperCase(),
|
||
),
|
||
o = !r || !i || !a;
|
||
return {
|
||
unit: n.unit,
|
||
options: (o ? [n] : t.map((e) => e.capacity)).map((e) => ({
|
||
value: e.size,
|
||
})),
|
||
presets: t,
|
||
selected: n,
|
||
choices: o,
|
||
};
|
||
}
|
||
function Je(e) {
|
||
return $(e)?.options ?? [];
|
||
}
|
||
function Ye(e) {
|
||
let t = N.value[String(e.id)];
|
||
return e.option_type === `select`
|
||
? $(e)?.selected?.size
|
||
: typeof t == `number`
|
||
? t
|
||
: void 0;
|
||
}
|
||
function Xe(e) {
|
||
return (
|
||
$(e)?.selected?.type ||
|
||
/\b(NVMe|SSD|HDD|SAS|SATA)\b/i.exec(e.option_name)?.[1] ||
|
||
($(e) ? `标准存储` : `存储选项`)
|
||
);
|
||
}
|
||
function Ze(e, t) {
|
||
if (G.value) return;
|
||
let n = $(e);
|
||
if (n) {
|
||
if (e.option_type === `select`) {
|
||
let r = n.presets?.find(
|
||
(e) => e.capacity?.size === t && e.capacity.unit === n.unit,
|
||
);
|
||
r && !n.choices && (N.value[String(e.id)] = r.id);
|
||
} else N.value[String(e.id)] = t;
|
||
}
|
||
}
|
||
let Qe = computed(() =>
|
||
Ie.value.map((e) => {
|
||
let t = N.value[String(e.id)],
|
||
n = ``;
|
||
if (e.option_type === `cascade`) {
|
||
let t = Re(e);
|
||
n = Z(e).find((e) => e.item_id === t)?.label ?? ``;
|
||
let r = Be(e);
|
||
r !== 1 && (n += ` × ${r}`);
|
||
} else if (
|
||
e.option_type === `quantity` ||
|
||
e.option_type === `quantity_range`
|
||
) {
|
||
let r = (Ue(e) ? $(e)?.unit : ``) || e.unit;
|
||
n = (
|
||
e.allow_repeat === 1 ? Q(e) : typeof t == `number` ? [t] : []
|
||
)
|
||
.map((e) => `${e}${r ? ` ${r}` : ``}`)
|
||
.join(`、`);
|
||
} else if (e.option_type === `os`)
|
||
n = os_name_t(
|
||
J.value
|
||
.get(e.id)
|
||
?.flatMap((e) => e.versions)
|
||
.find((e) => e.id === t)?.option_name,
|
||
);
|
||
else {
|
||
let r = Array.isArray(t) ? t : [t];
|
||
n = (e.subs ?? [])
|
||
.filter((e) => r.includes(e.id))
|
||
.map((t) => X(e, t.option_name))
|
||
.join(`、`);
|
||
}
|
||
return {
|
||
label: Y(e),
|
||
value: n || `未选择`,
|
||
};
|
||
}),
|
||
);
|
||
function $e(e) {
|
||
return (J.value.get(e.id) ?? []).map((e) => e.name);
|
||
}
|
||
function et(e) {
|
||
let t = N.value[String(e.id)];
|
||
return (
|
||
J.value.get(e.id)?.find((e) => e.versions.some((e) => e.id === t))
|
||
?.name ?? ``
|
||
);
|
||
}
|
||
function tt(e) {
|
||
return (
|
||
J.value.get(e.id)?.find((t) => t.name === et(e))?.versions ?? []
|
||
);
|
||
}
|
||
function nt(e, t) {
|
||
if (G.value || et(e) === t) return;
|
||
let n = J.value.get(e.id)?.find((e) => e.name === t)?.versions[0];
|
||
n && ((N.value[String(e.id)] = n.id), E.calcPrice());
|
||
}
|
||
async function rt() {
|
||
if (Fe.value) {
|
||
((W.value = `cart`),
|
||
(K.value = ``),
|
||
(q.value = ``),
|
||
clearTimeout(Pe));
|
||
try {
|
||
if ((await E.addToCart(), b.edit)) {
|
||
await navigateTo(`/cart`);
|
||
return;
|
||
}
|
||
((q.value = b.edit ? `购物车配置已更新` : `已加入购物车`),
|
||
(Pe = setTimeout(() => (q.value = ``), 4e3)));
|
||
} catch (e) {
|
||
K.value = e instanceof Error ? e.message : `提交失败,请重试`;
|
||
} finally {
|
||
W.value = null;
|
||
}
|
||
}
|
||
}
|
||
async function it() {
|
||
if (Fe.value) {
|
||
((W.value = `buy`), (K.value = ``), (q.value = ``));
|
||
try {
|
||
let e = await E.buyNow();
|
||
w(`settled`, e);
|
||
} catch (e) {
|
||
K.value = e instanceof Error ? e.message : `提交失败,请重试`;
|
||
} finally {
|
||
W.value = null;
|
||
}
|
||
}
|
||
}
|
||
return (
|
||
onMounted(() => E.init()),
|
||
(n, i) => {
|
||
let c = ConfigLoadingShell,
|
||
f = message,
|
||
h = button,
|
||
C = ConfigChoiceGrid,
|
||
w = select,
|
||
A = multiselect,
|
||
j = inputnumber,
|
||
ae = ProductCustomFields,
|
||
R = ConfigCheckout;
|
||
return (
|
||
openBlock(),
|
||
createElementBlock(`div`, le, [
|
||
unref(ce)
|
||
? (openBlock(),
|
||
createBlock(
|
||
c,
|
||
{
|
||
key: 0,
|
||
},
|
||
{
|
||
catalog: withCtx(() => [
|
||
renderSlot(
|
||
n.$slots,
|
||
`catalog`,
|
||
{
|
||
disabled: unref(W) !== null,
|
||
},
|
||
void 0,
|
||
!0,
|
||
),
|
||
]),
|
||
_: 3,
|
||
},
|
||
))
|
||
: unref(Te) && !unref(M)
|
||
? (openBlock(),
|
||
createElementBlock(`div`, ue, [
|
||
renderSlot(
|
||
n.$slots,
|
||
`catalog`,
|
||
{
|
||
disabled: unref(W) !== null,
|
||
},
|
||
void 0,
|
||
!0,
|
||
),
|
||
createVNode(
|
||
f,
|
||
{
|
||
severity: `error`,
|
||
closable: !1,
|
||
},
|
||
{
|
||
default: withCtx(() => [
|
||
createTextVNode(toDisplayString(unref(Te)), 1),
|
||
]),
|
||
_: 1,
|
||
},
|
||
),
|
||
createVNode(
|
||
h,
|
||
{
|
||
label: `重新加载配置`,
|
||
icon: `pi pi-refresh`,
|
||
severity: `secondary`,
|
||
outlined: ``,
|
||
disabled: o.identityLocked,
|
||
onClick: (i[0] ||= (e) => unref(E).init()),
|
||
},
|
||
null,
|
||
8,
|
||
[`disabled`],
|
||
),
|
||
]))
|
||
: unref(M)
|
||
? (openBlock(),
|
||
createElementBlock(`div`, de, [
|
||
createElementVNode(`div`, z, [
|
||
renderSlot(
|
||
n.$slots,
|
||
`catalog`,
|
||
{
|
||
disabled: unref(W) !== null,
|
||
},
|
||
void 0,
|
||
!0,
|
||
),
|
||
(openBlock(!0),
|
||
createElementBlock(
|
||
Fragment,
|
||
null,
|
||
renderList(
|
||
unref(Ge),
|
||
(n) => (
|
||
openBlock(),
|
||
createElementBlock(
|
||
`div`,
|
||
{
|
||
key: n.title,
|
||
class: `panel`,
|
||
},
|
||
[
|
||
createElementVNode(
|
||
`h2`,
|
||
fe,
|
||
toDisplayString(n.title),
|
||
1,
|
||
),
|
||
createElementVNode(
|
||
`div`,
|
||
{
|
||
class: normalizeClass({
|
||
"storage-grid":
|
||
n.title === `存储配置`,
|
||
}),
|
||
},
|
||
[
|
||
(openBlock(!0),
|
||
createElementBlock(
|
||
Fragment,
|
||
null,
|
||
renderList(
|
||
n.options,
|
||
(n) => (
|
||
openBlock(),
|
||
createElementBlock(
|
||
Fragment,
|
||
{
|
||
key: n.id,
|
||
},
|
||
[
|
||
n.option_type === `os`
|
||
? (openBlock(),
|
||
createElementBlock(
|
||
Fragment,
|
||
{
|
||
key: 0,
|
||
},
|
||
[
|
||
createElementVNode(
|
||
`div`,
|
||
pe,
|
||
[
|
||
(i[18] ||=
|
||
createElementVNode(
|
||
`label`,
|
||
null,
|
||
`操作系统`,
|
||
-1,
|
||
)),
|
||
createVNode(
|
||
C,
|
||
{
|
||
label: `操作系统`,
|
||
images: ``,
|
||
disabled:
|
||
unref(
|
||
G,
|
||
),
|
||
"model-value":
|
||
et(n),
|
||
options:
|
||
$e(
|
||
n,
|
||
).map(
|
||
(
|
||
e,
|
||
) => ({
|
||
label:
|
||
unref(
|
||
os_name_t,
|
||
)(
|
||
e,
|
||
),
|
||
value:
|
||
e,
|
||
}),
|
||
),
|
||
"onUpdate:modelValue":
|
||
(e) =>
|
||
nt(
|
||
n,
|
||
e,
|
||
),
|
||
},
|
||
null,
|
||
8,
|
||
[
|
||
`disabled`,
|
||
`model-value`,
|
||
`options`,
|
||
`onUpdate:modelValue`,
|
||
],
|
||
),
|
||
],
|
||
),
|
||
createElementVNode(
|
||
`div`,
|
||
me,
|
||
[
|
||
(i[19] ||=
|
||
createElementVNode(
|
||
`label`,
|
||
null,
|
||
`镜像版本`,
|
||
-1,
|
||
)),
|
||
createVNode(
|
||
w,
|
||
{
|
||
"aria-label": `镜像版本`,
|
||
disabled:
|
||
unref(
|
||
G,
|
||
),
|
||
modelValue:
|
||
unref(
|
||
N,
|
||
)[
|
||
String(
|
||
n.id,
|
||
)
|
||
],
|
||
"onUpdate:modelValue":
|
||
(e) =>
|
||
(unref(
|
||
N,
|
||
)[
|
||
String(
|
||
n.id,
|
||
)
|
||
] =
|
||
e),
|
||
options:
|
||
tt(n),
|
||
"option-label":
|
||
(e) =>
|
||
unref(
|
||
os_name_t,
|
||
)(
|
||
e.option_name,
|
||
),
|
||
optionValue: `id`,
|
||
class: `grow`,
|
||
onChange:
|
||
(i[1] ||=
|
||
(e) =>
|
||
unref(
|
||
E,
|
||
).calcPrice()),
|
||
},
|
||
null,
|
||
8,
|
||
[
|
||
`disabled`,
|
||
`modelValue`,
|
||
`onUpdate:modelValue`,
|
||
`options`,
|
||
`option-label`,
|
||
],
|
||
),
|
||
],
|
||
),
|
||
],
|
||
64,
|
||
))
|
||
: Ue(n) &&
|
||
((n.option_type !==
|
||
`quantity` &&
|
||
n.option_type !==
|
||
`quantity_range`) ||
|
||
n.allow_repeat !==
|
||
1)
|
||
? (openBlock(),
|
||
createBlock(
|
||
ConfigDiskCard,
|
||
{
|
||
key: 1,
|
||
label: Y(n),
|
||
title: Xe(n),
|
||
"model-value":
|
||
Ye(n),
|
||
options: Je(n),
|
||
unit:
|
||
$(n)?.unit ||
|
||
n.unit ||
|
||
``,
|
||
description:
|
||
n.description,
|
||
disabled:
|
||
unref(G),
|
||
class: `common-storage`,
|
||
"onUpdate:modelValue":
|
||
(e) =>
|
||
Ze(n, e),
|
||
onChange:
|
||
(i[6] ||= (
|
||
e,
|
||
) =>
|
||
unref(
|
||
E,
|
||
).calcPrice()),
|
||
},
|
||
createSlots(
|
||
{
|
||
_: 2,
|
||
},
|
||
[
|
||
$(n)?.choices
|
||
? {
|
||
name: `type`,
|
||
fn: withCtx(
|
||
() => [
|
||
createVNode(
|
||
C,
|
||
{
|
||
label: `${Y(n)}规格`,
|
||
compact: ``,
|
||
disabled:
|
||
unref(
|
||
G,
|
||
),
|
||
modelValue:
|
||
unref(
|
||
N,
|
||
)[
|
||
String(
|
||
n.id,
|
||
)
|
||
],
|
||
"onUpdate:modelValue":
|
||
(
|
||
e,
|
||
) =>
|
||
(unref(
|
||
N,
|
||
)[
|
||
String(
|
||
n.id,
|
||
)
|
||
] =
|
||
e),
|
||
options:
|
||
(
|
||
n.subs ||
|
||
[]
|
||
).map(
|
||
(
|
||
e,
|
||
) => ({
|
||
label:
|
||
X(
|
||
n,
|
||
e.option_name,
|
||
),
|
||
value:
|
||
e.id,
|
||
}),
|
||
),
|
||
onChange:
|
||
(i[2] ||=
|
||
(
|
||
e,
|
||
) =>
|
||
unref(
|
||
E,
|
||
).calcPrice()),
|
||
},
|
||
null,
|
||
8,
|
||
[
|
||
`label`,
|
||
`disabled`,
|
||
`modelValue`,
|
||
`onUpdate:modelValue`,
|
||
`options`,
|
||
],
|
||
),
|
||
],
|
||
),
|
||
key: `0`,
|
||
}
|
||
: void 0,
|
||
Je(n).length
|
||
? void 0
|
||
: {
|
||
name: `default`,
|
||
fn: withCtx(
|
||
() => [
|
||
n.option_type ===
|
||
`multi_select`
|
||
? (openBlock(),
|
||
createBlock(
|
||
A,
|
||
{
|
||
key: 0,
|
||
"aria-label":
|
||
Y(
|
||
n,
|
||
),
|
||
disabled:
|
||
unref(
|
||
G,
|
||
),
|
||
modelValue:
|
||
unref(
|
||
N,
|
||
)[
|
||
String(
|
||
n.id,
|
||
)
|
||
],
|
||
"onUpdate:modelValue":
|
||
(
|
||
e,
|
||
) =>
|
||
(unref(
|
||
N,
|
||
)[
|
||
String(
|
||
n.id,
|
||
)
|
||
] =
|
||
e),
|
||
options:
|
||
n.subs,
|
||
"option-label":
|
||
(
|
||
e,
|
||
) =>
|
||
X(
|
||
n,
|
||
e.option_name,
|
||
),
|
||
optionValue: `id`,
|
||
display: `chip`,
|
||
class: `grow`,
|
||
onChange:
|
||
(i[3] ||=
|
||
(
|
||
e,
|
||
) =>
|
||
unref(
|
||
E,
|
||
).calcPrice()),
|
||
},
|
||
null,
|
||
8,
|
||
[
|
||
`aria-label`,
|
||
`disabled`,
|
||
`modelValue`,
|
||
`onUpdate:modelValue`,
|
||
`options`,
|
||
`option-label`,
|
||
],
|
||
))
|
||
: n.option_type ===
|
||
`quantity` ||
|
||
n.option_type ===
|
||
`quantity_range`
|
||
? (openBlock(),
|
||
createBlock(
|
||
j,
|
||
{
|
||
key: 1,
|
||
"aria-label":
|
||
Y(
|
||
n,
|
||
),
|
||
disabled:
|
||
unref(
|
||
G,
|
||
),
|
||
modelValue:
|
||
unref(
|
||
N,
|
||
)[
|
||
String(
|
||
n.id,
|
||
)
|
||
],
|
||
"onUpdate:modelValue":
|
||
[
|
||
(
|
||
e,
|
||
) =>
|
||
(unref(
|
||
N,
|
||
)[
|
||
String(
|
||
n.id,
|
||
)
|
||
] =
|
||
e),
|
||
(i[4] ||=
|
||
(
|
||
e,
|
||
) =>
|
||
unref(
|
||
E,
|
||
).calcPrice()),
|
||
],
|
||
min:
|
||
n.qty_min ??
|
||
1,
|
||
max:
|
||
n.qty_max ||
|
||
void 0,
|
||
step:
|
||
n.qty_change ||
|
||
1,
|
||
showButtons: ``,
|
||
buttonLayout: `horizontal`,
|
||
suffix:
|
||
n.unit
|
||
? ` ${n.unit}`
|
||
: ``,
|
||
},
|
||
null,
|
||
8,
|
||
[
|
||
`aria-label`,
|
||
`disabled`,
|
||
`modelValue`,
|
||
`onUpdate:modelValue`,
|
||
`min`,
|
||
`max`,
|
||
`step`,
|
||
`suffix`,
|
||
],
|
||
))
|
||
: (openBlock(),
|
||
createBlock(
|
||
C,
|
||
{
|
||
key: 2,
|
||
label:
|
||
Y(
|
||
n,
|
||
),
|
||
compact: ``,
|
||
disabled:
|
||
unref(
|
||
G,
|
||
),
|
||
modelValue:
|
||
unref(
|
||
N,
|
||
)[
|
||
String(
|
||
n.id,
|
||
)
|
||
],
|
||
"onUpdate:modelValue":
|
||
(
|
||
e,
|
||
) =>
|
||
(unref(
|
||
N,
|
||
)[
|
||
String(
|
||
n.id,
|
||
)
|
||
] =
|
||
e),
|
||
options:
|
||
(
|
||
n.subs ||
|
||
[]
|
||
).map(
|
||
(
|
||
e,
|
||
) => ({
|
||
label:
|
||
X(
|
||
n,
|
||
e.option_name,
|
||
),
|
||
value:
|
||
e.id,
|
||
}),
|
||
),
|
||
onChange:
|
||
(i[5] ||=
|
||
(
|
||
e,
|
||
) =>
|
||
unref(
|
||
E,
|
||
).calcPrice()),
|
||
},
|
||
null,
|
||
8,
|
||
[
|
||
`label`,
|
||
`disabled`,
|
||
`modelValue`,
|
||
`onUpdate:modelValue`,
|
||
`options`,
|
||
],
|
||
)),
|
||
],
|
||
),
|
||
key: `1`,
|
||
},
|
||
],
|
||
),
|
||
1032,
|
||
[
|
||
`label`,
|
||
`title`,
|
||
`model-value`,
|
||
`options`,
|
||
`unit`,
|
||
`description`,
|
||
`disabled`,
|
||
`onUpdate:modelValue`,
|
||
],
|
||
))
|
||
: n.option_type ===
|
||
`multi_select`
|
||
? (openBlock(),
|
||
createElementBlock(
|
||
`div`,
|
||
he,
|
||
[
|
||
createElementVNode(
|
||
`label`,
|
||
null,
|
||
toDisplayString(
|
||
Y(n),
|
||
),
|
||
1,
|
||
),
|
||
createVNode(
|
||
A,
|
||
{
|
||
"aria-label":
|
||
Y(n),
|
||
disabled:
|
||
unref(
|
||
G,
|
||
),
|
||
modelValue:
|
||
unref(
|
||
N,
|
||
)[
|
||
String(
|
||
n.id,
|
||
)
|
||
],
|
||
"onUpdate:modelValue":
|
||
(e) =>
|
||
(unref(
|
||
N,
|
||
)[
|
||
String(
|
||
n.id,
|
||
)
|
||
] =
|
||
e),
|
||
options:
|
||
n.subs,
|
||
"option-label":
|
||
(e) =>
|
||
X(
|
||
n,
|
||
e.option_name,
|
||
),
|
||
optionValue: `id`,
|
||
display: `chip`,
|
||
class: `grow`,
|
||
onChange:
|
||
(i[7] ||=
|
||
(e) =>
|
||
unref(
|
||
E,
|
||
).calcPrice()),
|
||
},
|
||
null,
|
||
8,
|
||
[
|
||
`aria-label`,
|
||
`disabled`,
|
||
`modelValue`,
|
||
`onUpdate:modelValue`,
|
||
`options`,
|
||
`option-label`,
|
||
],
|
||
),
|
||
],
|
||
))
|
||
: n.option_type ===
|
||
`cascade`
|
||
? (openBlock(),
|
||
createElementBlock(
|
||
`div`,
|
||
B,
|
||
[
|
||
createElementVNode(
|
||
`label`,
|
||
null,
|
||
toDisplayString(
|
||
Y(n),
|
||
),
|
||
1,
|
||
),
|
||
createElementVNode(
|
||
`div`,
|
||
V,
|
||
[
|
||
createVNode(
|
||
w,
|
||
{
|
||
"aria-label":
|
||
Y(
|
||
n,
|
||
),
|
||
disabled:
|
||
unref(
|
||
G,
|
||
) ||
|
||
!Z(
|
||
n,
|
||
)
|
||
.length,
|
||
"model-value":
|
||
Re(
|
||
n,
|
||
),
|
||
options:
|
||
Z(
|
||
n,
|
||
),
|
||
"option-label": `label`,
|
||
"option-value": `item_id`,
|
||
class: `grow`,
|
||
placeholder: `请选择配置`,
|
||
"onUpdate:modelValue":
|
||
(
|
||
e,
|
||
) =>
|
||
ze(
|
||
n,
|
||
e,
|
||
),
|
||
},
|
||
null,
|
||
8,
|
||
[
|
||
`aria-label`,
|
||
`disabled`,
|
||
`model-value`,
|
||
`options`,
|
||
`onUpdate:modelValue`,
|
||
],
|
||
),
|
||
unref(
|
||
De,
|
||
)[
|
||
String(
|
||
n.id,
|
||
)
|
||
]
|
||
? (openBlock(),
|
||
createBlock(
|
||
j,
|
||
{
|
||
key: 0,
|
||
"aria-label": `${Y(n)}数量`,
|
||
disabled:
|
||
unref(
|
||
G,
|
||
),
|
||
"model-value":
|
||
Be(
|
||
n,
|
||
),
|
||
min: 1,
|
||
"show-buttons": ``,
|
||
"button-layout": `horizontal`,
|
||
"onUpdate:modelValue":
|
||
(
|
||
e,
|
||
) =>
|
||
Ve(
|
||
n,
|
||
e,
|
||
),
|
||
},
|
||
null,
|
||
8,
|
||
[
|
||
`aria-label`,
|
||
`disabled`,
|
||
`model-value`,
|
||
`onUpdate:modelValue`,
|
||
],
|
||
))
|
||
: createCommentVNode(
|
||
``,
|
||
!0,
|
||
),
|
||
],
|
||
),
|
||
Z(n).length
|
||
? n.description
|
||
? (openBlock(),
|
||
createElementBlock(
|
||
`span`,
|
||
_e,
|
||
toDisplayString(
|
||
n.description,
|
||
),
|
||
1,
|
||
))
|
||
: createCommentVNode(
|
||
``,
|
||
!0,
|
||
)
|
||
: (openBlock(),
|
||
createElementBlock(
|
||
`span`,
|
||
ge,
|
||
`当前商品暂未提供可用的级联选项`,
|
||
)),
|
||
],
|
||
))
|
||
: n.option_type ===
|
||
`quantity` ||
|
||
n.option_type ===
|
||
`quantity_range`
|
||
? (openBlock(),
|
||
createElementBlock(
|
||
`div`,
|
||
H,
|
||
[
|
||
createElementVNode(
|
||
`label`,
|
||
null,
|
||
toDisplayString(
|
||
Y(n),
|
||
),
|
||
1,
|
||
),
|
||
n.allow_repeat ===
|
||
1
|
||
? (openBlock(),
|
||
createElementBlock(
|
||
`div`,
|
||
ve,
|
||
[
|
||
(openBlock(
|
||
!0,
|
||
),
|
||
createElementBlock(
|
||
Fragment,
|
||
null,
|
||
renderList(
|
||
Q(
|
||
n,
|
||
),
|
||
(
|
||
t,
|
||
r,
|
||
) => (
|
||
openBlock(),
|
||
createElementBlock(
|
||
`div`,
|
||
{
|
||
key: `${n.id}-${r}`,
|
||
class: `repeat-row`,
|
||
},
|
||
[
|
||
createElementVNode(
|
||
`span`,
|
||
ye,
|
||
toDisplayString(
|
||
Y(
|
||
n,
|
||
),
|
||
) +
|
||
toDisplayString(
|
||
r +
|
||
1,
|
||
),
|
||
1,
|
||
),
|
||
createVNode(
|
||
j,
|
||
{
|
||
"aria-label": `${Y(n)}${r + 1}`,
|
||
disabled:
|
||
unref(
|
||
G,
|
||
),
|
||
"model-value":
|
||
t,
|
||
min:
|
||
n.qty_min ??
|
||
1,
|
||
max:
|
||
n.qty_max ||
|
||
void 0,
|
||
step:
|
||
n.qty_change ||
|
||
1,
|
||
"show-buttons": ``,
|
||
"button-layout": `horizontal`,
|
||
suffix:
|
||
n.unit
|
||
? ` ${n.unit}`
|
||
: ``,
|
||
"onUpdate:modelValue":
|
||
(
|
||
e,
|
||
) =>
|
||
He(
|
||
n,
|
||
r,
|
||
e,
|
||
),
|
||
},
|
||
null,
|
||
8,
|
||
[
|
||
`aria-label`,
|
||
`disabled`,
|
||
`model-value`,
|
||
`min`,
|
||
`max`,
|
||
`step`,
|
||
`suffix`,
|
||
`onUpdate:modelValue`,
|
||
],
|
||
),
|
||
Q(
|
||
n,
|
||
)
|
||
.length >
|
||
1
|
||
? (openBlock(),
|
||
createBlock(
|
||
h,
|
||
{
|
||
key: 0,
|
||
icon: `pi pi-trash`,
|
||
text: ``,
|
||
severity: `danger`,
|
||
size: `small`,
|
||
disabled:
|
||
unref(
|
||
G,
|
||
),
|
||
"aria-label": `删除${Y(n)}${r + 1}`,
|
||
onClick:
|
||
(
|
||
e,
|
||
) =>
|
||
unref(
|
||
E,
|
||
).removeRepeat(
|
||
n.id,
|
||
r,
|
||
),
|
||
},
|
||
null,
|
||
8,
|
||
[
|
||
`disabled`,
|
||
`aria-label`,
|
||
`onClick`,
|
||
],
|
||
))
|
||
: createCommentVNode(
|
||
``,
|
||
!0,
|
||
),
|
||
],
|
||
)
|
||
),
|
||
),
|
||
128,
|
||
)),
|
||
Q(
|
||
n,
|
||
)
|
||
.length <
|
||
Math.max(
|
||
1,
|
||
Number(
|
||
n.max_repeat ||
|
||
1,
|
||
),
|
||
)
|
||
? (openBlock(),
|
||
createBlock(
|
||
h,
|
||
{
|
||
key: 0,
|
||
label: `添加一项`,
|
||
icon: `pi pi-plus`,
|
||
text: ``,
|
||
severity: `secondary`,
|
||
size: `small`,
|
||
disabled:
|
||
unref(
|
||
G,
|
||
),
|
||
onClick:
|
||
(
|
||
e,
|
||
) =>
|
||
unref(
|
||
E,
|
||
).addRepeat(
|
||
n.id,
|
||
),
|
||
},
|
||
null,
|
||
8,
|
||
[
|
||
`disabled`,
|
||
`onClick`,
|
||
],
|
||
))
|
||
: createCommentVNode(
|
||
``,
|
||
!0,
|
||
),
|
||
],
|
||
))
|
||
: (openBlock(),
|
||
createBlock(
|
||
j,
|
||
{
|
||
key: 1,
|
||
"aria-label":
|
||
Y(
|
||
n,
|
||
),
|
||
disabled:
|
||
unref(
|
||
G,
|
||
),
|
||
modelValue:
|
||
unref(
|
||
N,
|
||
)[
|
||
String(
|
||
n.id,
|
||
)
|
||
],
|
||
"onUpdate:modelValue":
|
||
[
|
||
(
|
||
e,
|
||
) =>
|
||
(unref(
|
||
N,
|
||
)[
|
||
String(
|
||
n.id,
|
||
)
|
||
] =
|
||
e),
|
||
(i[8] ||=
|
||
(
|
||
e,
|
||
) =>
|
||
unref(
|
||
E,
|
||
).calcPrice()),
|
||
],
|
||
min:
|
||
n.qty_min ??
|
||
1,
|
||
max:
|
||
n.qty_max ||
|
||
void 0,
|
||
step:
|
||
n.qty_change ||
|
||
1,
|
||
"show-buttons": ``,
|
||
"button-layout": `horizontal`,
|
||
suffix:
|
||
n.unit
|
||
? ` ${n.unit}`
|
||
: ``,
|
||
},
|
||
null,
|
||
8,
|
||
[
|
||
`aria-label`,
|
||
`disabled`,
|
||
`modelValue`,
|
||
`onUpdate:modelValue`,
|
||
`min`,
|
||
`max`,
|
||
`step`,
|
||
`suffix`,
|
||
],
|
||
)),
|
||
n.description
|
||
? (openBlock(),
|
||
createElementBlock(
|
||
`span`,
|
||
U,
|
||
toDisplayString(
|
||
n.description,
|
||
),
|
||
1,
|
||
))
|
||
: createCommentVNode(
|
||
``,
|
||
!0,
|
||
),
|
||
],
|
||
))
|
||
: (openBlock(),
|
||
createElementBlock(
|
||
`div`,
|
||
be,
|
||
[
|
||
createElementVNode(
|
||
`label`,
|
||
null,
|
||
toDisplayString(
|
||
Y(n),
|
||
),
|
||
1,
|
||
),
|
||
createVNode(
|
||
C,
|
||
{
|
||
label:
|
||
Y(
|
||
n,
|
||
),
|
||
compact:
|
||
!Le(
|
||
n,
|
||
),
|
||
disabled:
|
||
unref(
|
||
G,
|
||
),
|
||
modelValue:
|
||
unref(
|
||
N,
|
||
)[
|
||
String(
|
||
n.id,
|
||
)
|
||
],
|
||
"onUpdate:modelValue":
|
||
(
|
||
e,
|
||
) =>
|
||
(unref(
|
||
N,
|
||
)[
|
||
String(
|
||
n.id,
|
||
)
|
||
] =
|
||
e),
|
||
options:
|
||
(
|
||
n.subs ||
|
||
[]
|
||
).map(
|
||
(
|
||
e,
|
||
) => ({
|
||
label:
|
||
X(
|
||
n,
|
||
e.option_name,
|
||
),
|
||
value:
|
||
e.id,
|
||
}),
|
||
),
|
||
onChange:
|
||
(i[9] ||=
|
||
(
|
||
e,
|
||
) =>
|
||
unref(
|
||
E,
|
||
).calcPrice()),
|
||
},
|
||
null,
|
||
8,
|
||
[
|
||
`label`,
|
||
`compact`,
|
||
`disabled`,
|
||
`modelValue`,
|
||
`onUpdate:modelValue`,
|
||
`options`,
|
||
],
|
||
),
|
||
n.description
|
||
? (openBlock(),
|
||
createElementBlock(
|
||
`span`,
|
||
xe,
|
||
toDisplayString(
|
||
n.description,
|
||
),
|
||
1,
|
||
))
|
||
: createCommentVNode(
|
||
``,
|
||
!0,
|
||
),
|
||
],
|
||
)),
|
||
],
|
||
64,
|
||
)
|
||
),
|
||
),
|
||
128,
|
||
)),
|
||
],
|
||
2,
|
||
),
|
||
],
|
||
)
|
||
),
|
||
),
|
||
128,
|
||
)),
|
||
createVNode(
|
||
ae,
|
||
{
|
||
modelValue: unref(Me),
|
||
"onUpdate:modelValue": (i[10] ||= (e) =>
|
||
isRef(Me) ? (Me.value = e) : null),
|
||
fields: unref(Ne),
|
||
disabled: unref(G),
|
||
},
|
||
null,
|
||
8,
|
||
[`modelValue`, `fields`, `disabled`],
|
||
),
|
||
]),
|
||
createVNode(
|
||
R,
|
||
{
|
||
"product-id": b.productId,
|
||
quantity: unref(I),
|
||
"edit-position": b.edit?.position,
|
||
editing: !!b.edit,
|
||
summary: unref(Qe),
|
||
price: unref(oe),
|
||
"quote-ready": unref(Ee) && !o.identityLocked,
|
||
"price-loading": unref(we),
|
||
"can-submit": unref(Fe),
|
||
"active-action": unref(W),
|
||
disabled: unref(G),
|
||
"promo-code": unref(ke),
|
||
"onUpdate:promoCode": (i[15] ||= (e) =>
|
||
isRef(ke) ? (ke.value = e) : null),
|
||
"promo-discount": unref(Ae),
|
||
"level-discount": unref(je),
|
||
error: unref(Te),
|
||
"action-error": unref(K),
|
||
"cart-tip": unref(q),
|
||
onCart: rt,
|
||
onBuy: it,
|
||
onRecalc: (i[16] ||= (e) =>
|
||
unref(E).calcPrice()),
|
||
onRetry: (i[17] ||= (e) =>
|
||
unref(E).calcPrice()),
|
||
},
|
||
{
|
||
default: withCtx(() => [
|
||
createElementVNode(`div`, Se, [
|
||
createElementVNode(
|
||
`label`,
|
||
null,
|
||
toDisplayString(
|
||
[
|
||
`free`,
|
||
`onetime`,
|
||
`recurring_postpaid`,
|
||
].includes(
|
||
unref(M).common_product?.pay_type,
|
||
)
|
||
? `计费方式`
|
||
: `购买时长`,
|
||
),
|
||
1,
|
||
),
|
||
createVNode(
|
||
w,
|
||
{
|
||
"aria-label": `购买时长`,
|
||
disabled:
|
||
unref(G) || unref(ie).length <= 1,
|
||
modelValue: unref(te),
|
||
"onUpdate:modelValue": (i[11] ||= (
|
||
e,
|
||
) =>
|
||
isRef(te) ? (te.value = e) : null),
|
||
options: unref(ie),
|
||
optionLabel: `label`,
|
||
optionValue: `value`,
|
||
placeholder: `请选择周期`,
|
||
class: `grow`,
|
||
onChange: (i[12] ||= (e) =>
|
||
unref(E).calcPrice()),
|
||
},
|
||
null,
|
||
8,
|
||
[`disabled`, `modelValue`, `options`],
|
||
),
|
||
]),
|
||
unref(M).common_product.allow_qty === 1
|
||
? (openBlock(),
|
||
createElementBlock(`div`, Ce, [
|
||
(i[20] ||= createElementVNode(
|
||
`label`,
|
||
null,
|
||
`购买数量`,
|
||
-1,
|
||
)),
|
||
createVNode(
|
||
j,
|
||
{
|
||
"aria-label": `购买数量`,
|
||
disabled: unref(G),
|
||
modelValue: unref(I),
|
||
"onUpdate:modelValue": [
|
||
(i[13] ||= (e) =>
|
||
isRef(I)
|
||
? (I.value = e)
|
||
: null),
|
||
(i[14] ||= (e) =>
|
||
unref(E).calcPrice()),
|
||
],
|
||
min: 1,
|
||
showButtons: ``,
|
||
buttonLayout: `horizontal`,
|
||
},
|
||
null,
|
||
8,
|
||
[`disabled`, `modelValue`],
|
||
),
|
||
]))
|
||
: createCommentVNode(``, !0),
|
||
]),
|
||
_: 1,
|
||
},
|
||
8,
|
||
[
|
||
`product-id`,
|
||
`quantity`,
|
||
`edit-position`,
|
||
`editing`,
|
||
`summary`,
|
||
`price`,
|
||
`quote-ready`,
|
||
`price-loading`,
|
||
`can-submit`,
|
||
`active-action`,
|
||
`disabled`,
|
||
`promo-code`,
|
||
`promo-discount`,
|
||
`level-discount`,
|
||
`error`,
|
||
`action-error`,
|
||
`cart-tip`,
|
||
],
|
||
),
|
||
]))
|
||
: createCommentVNode(``, !0),
|
||
])
|
||
);
|
||
}
|
||
);
|
||
},
|
||
}),
|
||
[[`__scopeId`, `data-v-bc59a2b1`]],
|
||
),
|
||
{
|
||
__name: `CommonConfig`,
|
||
},
|
||
);
|
||
export {};
|
||
export default we;
|
||
</script>
|