Files
console-dev/app/components/config/CommonConfig.vue
T
2026-11-06 00:04:38 +08:00

2479 lines
138 KiB
Vue
Raw 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.
<script>
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 R(e, t = {}) {
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() {
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 = fe(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 fe(e) {
let t = (e) => e.flatMap((e) => (e.children?.length ? t(e.children) : [e]));
return t(e.tree ?? []).filter((e) => Number(e.hidden) !== 1);
}
function pe(e, t, n = 1) {
let r = l.value?.configoptions.find((t) => t.id === e);
r &&
r.option_type === `cascade` &&
fe(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);
return Number.isFinite(r)
? [
[
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) {
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() {
(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) {
let t = [],
n = (e, r) => {
for (let i of e) {
if (!i || typeof i != `object` || Array.isArray(i)) continue;
let e = i;
if (Number(e.hidden) === 1) continue;
let a = String(e.item_name ?? ``).trim(),
o = a ? [...r, a] : r,
s = Array.isArray(e.children) ? e.children : [],
c = Number(e.item_id);
(Number(e.is_leaf) === 1 || s.length === 0) &&
Number.isInteger(c) &&
c > 0
? t.push({
item_id: c,
label: o.join(` / `) || `选项 ${c}`,
})
: s.length && n(s, o);
}
};
return (
n(e.tree ?? [], []),
t
.sort((e, t) => e.label.localeCompare(t.label, `zh-Hans-CN`))
.filter(
(e, t, n) =>
n.findIndex((t) => t.item_id === e.item_id) === t,
)
);
}
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>