Files

2299 lines
103 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script>
/** 智简云/独立服务器配置页;module 决定接口命名空间,jy_dcim 额外将带宽变体归并为硬件型号。 */
import "~/assets/styles/ConfigResourceOption.Dj4VopnA.css";
import "~/assets/styles/ConfigDiskAdd.C92e9ZuF.css";
import "~/assets/styles/ConfigBandwidth.CWSH1WJZ.css";
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/JyCloudConfig.kGfttaHi.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 { 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 { 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 { r as cart_edit_r } from "~/lib/cart-edit.js";
import ConfigDiskCard from "~/components/config/ConfigDiskCard.vue";
import ConfigBandwidth from "~/components/config/ConfigBandwidth.vue";
import ConfigDiskAdd from "~/components/config/ConfigDiskAdd.vue";
import ConfigResourceOption from "~/components/config/ConfigResourceOption.vue";
function P(e) {
let t = String(e ?? ``).trim();
if (!t) return `未提供`;
let n = t.match(
/^(\d+(?:\.\d+)?)\s*(GB|TB)\s*(?:(\d+)\s*个\s*)?(SSD|NVME|HDD)$/i,
);
if (!n) return t;
let r = Number(n[1]),
i = n[2].toUpperCase(),
a = Number(n[3] || 1),
o = n[4].toUpperCase() === `NVME` ? `NVMe` : n[4].toUpperCase(),
s =
i === `TB`
? `${r}T`
: r >= 1e3 && (r % 1e3 == 0 || r % 1024 == 0)
? `${r % 1e3 == 0 ? r / 1e3 : r / 1024}T`
: `${r}G`;
return `${a > 1 ? `${a} × ` : ``}${s} ${o}`;
}
var F = (e, t) => String(e) === String(t);
function I(e) {
return e
.trim()
.replace(/\s*-\s*\d+(?:\.\d+)?\s*(?:Mbps|M)\b.*$/i, ``)
.replace(/\s*-\s*\d+(?:\.\d+)?\s*GB?$/i, ``)
.trim();
}
function le(e) {
// 同名、同 CPU/内存/磁盘的套餐按带宽排序为同一型号,切换带宽仍需选择真实套餐 ID。
let t = new Map();
for (let n of e) {
let e = I(n.name || ``),
r = String(n.disk_desc ?? ``).trim(),
i = [
e.toLocaleLowerCase(),
Number(n.cpu_num) || 0,
Number(n.memory) || 0,
r.toLocaleLowerCase(),
].join(`|`),
a = t.get(i) ?? [];
(a.push(n), t.set(i, a));
}
return [...t.entries()].map(([e, t]) => {
let n = [...t].sort(
(e, t) =>
(Number(e.bw_size) || 0) - (Number(t.bw_size) || 0) ||
Number(e.id) - Number(t.id),
),
r = n[0],
i = I(r.name || ``),
a = Number(r.cpu_num) || 0;
return {
key: e,
name: i || r.name.trim(),
processorParameters: a ? `${a} 颗` : `—`,
memory: Number(r.memory) || 0,
disk: P(r.disk_desc),
bandwidth: Number(r.bw_size) || 0,
package: r,
variants: n,
};
});
}
function L(e, t, n) {
return `/product/${e}/${t}/${n}`;
}
function ue() {
return {
line_id: ``,
line_name: ``,
node_id: ``,
node_name: ``,
package_config_id: ``,
package_name: ``,
cpu_num: 0,
memory: 0,
image_id: ``,
image_name: ``,
system_disk: {
size: 0,
type: ``,
},
data_disk: [],
bill_method: `bw`,
bandwidth: 0,
ip_num: 0,
protect: 0,
defense: 0,
duration_id: ``,
duration_name: ``,
notes: ``,
auto_renew: !1,
qty: 1,
};
}
function R(e, t, n, r) {
let i = Number.isFinite(t) ? t : 0,
a = Number.isFinite(n) && n >= i ? n : i,
o = Number.isFinite(r) && r > 0 ? r : 1,
s = Number.isFinite(Number(e)) ? Number(e) : i;
return Math.min(a, Math.max(i, i + Math.round((s - i) / o) * o));
}
function z(e, t, n = {}) {
// 配置、优惠码和自定义字段组成报价快照;只有快照与最近报价一致时才允许提交。
let r = useApi(),
a = n.edit,
s = cart_edit_r(r, a),
l = shallowRef(null),
u = ref([]),
f = ref([]),
p = ref({}),
m = ref([]),
h = ref(ue()),
te = ref(`—`),
g = ref(``),
_ = ref(0),
v = ref(0),
y = ref(!0),
b = ref(!1),
S = ref(``),
C = !1,
w = 0,
T = 0,
E = ref(``),
D = computed(() =>
JSON.stringify({
config: h.value,
promo: g.value,
customFields: p.value,
}),
),
ie = computed(() => !!E.value && E.value === D.value && !b.value);
function k() {
(T++,
(E.value = ``),
(te.value = `—`),
(_.value = 0),
(v.value = 0),
(b.value = !1));
}
(watch(D, k, {
flush: `sync`,
}),
onBeforeUnmount(() => {
((C = !0), w++, k());
}));
let A = computed(
() =>
l.value?.package.find((e) => F(e.id, h.value.package_config_id)) ??
null,
),
j = computed(() =>
t === `jy_dcim`
? le(
(l.value?.package ?? []).filter(
(e) =>
(!Number(e.line_id) || F(e.line_id, h.value.line_id)) &&
(!Number(e.node_id) || F(e.node_id, h.value.node_id)),
),
)
: [],
),
ae = computed(() => (A.value && Number(A.value.data_disk_max) > 0 ? 1 : 0));
function oe(e) {
// 套餐变化同步约束所有附属资源;protect/defense 两字段保留现有后端协议要求。
if (!e) return;
let t = h.value.package_config_id;
((h.value.package_config_id = e.id),
(h.value.package_name = e.name),
(h.value.cpu_num = Number(e.cpu_num) || 0),
(h.value.memory = Number(e.memory) || 0),
(h.value.system_disk.size = R(
h.value.system_disk.size,
Number(e.system_disk_size),
Number(e.system_disk_max),
Number(e.system_disk_step),
)),
F(t, e.id) ||
(h.value.data_disk = [
{
size: Number(e.data_disk_size),
type: ``,
},
]),
(h.value.data_disk = h.value.data_disk.map((t) => ({
...t,
size: R(
t.size,
Number(e.data_disk_size),
Number(e.data_disk_max),
Number(e.data_disk_step),
),
}))),
(h.value.bill_method =
Number(e.traffic_bw_status) === 1 && Number(e.bw_status) !== 1
? `flow`
: `bw`),
(h.value.bandwidth = R(
h.value.bandwidth,
Number(e.bw_size),
Number(e.bw_max),
Number(e.bw_step),
)),
(h.value.ip_num = R(
h.value.ip_num,
Number(e.ip_size),
Number(e.ip_max),
Number(e.ip_step),
)),
(h.value.protect = R(
h.value.protect,
Number(e.defense_size),
Number(e.defense_max),
Number(e.defense_step),
)),
(h.value.defense = h.value.protect));
}
function se() {
let e = l.value;
if (!e) return;
let t = e.line.find((e) => F(e.id, h.value.line_id)) ?? e.line[0],
n = e.node.find((e) => F(e.id, h.value.node_id)) ?? e.node[0];
(t && ((h.value.line_id = t.id), (h.value.line_name = t.name)),
n && ((h.value.node_id = n.id), (h.value.node_name = n.name)),
oe(
e.package.find((e) => F(e.id, h.value.package_config_id)) ??
e.package[0] ??
null,
));
}
function ce() {
let e = u.value.flatMap((e) => e.image ?? []),
t = e.find((e) => F(e.id, h.value.image_id)) ?? e[0];
t && ((h.value.image_id = t.id), (h.value.image_name = t.name));
}
function P() {
let e = a?.item.config_options;
if (!e || typeof e != `object` || Array.isArray(e)) return;
let t = cart_edit_n(e);
h.value = {
...h.value,
...t,
system_disk: {
...h.value.system_disk,
...(t.system_disk ?? {}),
},
data_disk: Array.isArray(t.data_disk) ? t.data_disk : h.value.data_disk,
qty: Math.max(1, Number(a?.item.qty ?? t.qty ?? 1)),
};
let n = a?.item.customfield;
n &&
typeof n == `object` &&
!Array.isArray(n) &&
(g.value = String(n.promo_code ?? ``));
let r = a?.item.self_defined_field;
if (r && typeof r == `object` && !Array.isArray(r))
for (let e of m.value) p.value[e.id] = String(r[e.id] ?? ``);
}
async function I(n) {
let i = await r.get(L(e, t, `order_page`), {
...(h.value.line_id
? {
line_id: h.value.line_id,
}
: {}),
...(h.value.node_id
? {
node_id: h.value.node_id,
}
: {}),
});
return C || n !== w ? !1 : ((l.value = i), se(), !0);
}
async function z(n) {
if (!h.value.node_id) return !1;
let i = await r.get(L(e, t, `image`), {
node_id: h.value.node_id,
});
return C || n !== w ? !1 : ((u.value = i.list ?? []), ce(), !0);
}
async function de(n) {
let i = await r.post(
L(e, t, `duration`),
{
id: e,
...h.value,
},
!1,
{
allowStatuslessDataArray: !0,
},
);
if (C || n !== w) return !1;
f.value = Array.isArray(i) ? i : [];
let a = f.value.find((e) => F(e.id, h.value.duration_id)) ?? f.value[0];
return (
a && ((h.value.duration_id = a.id), (h.value.duration_name = a.name)),
!0
);
}
async function B() {
// 金额只接受有限非负数,响应还必须匹配当前代次与输入快照。
if (
(k(),
C ||
!h.value.duration_id ||
!h.value.image_id ||
!h.value.package_config_id)
)
return;
h.value.defense = h.value.protect;
let t = ++T,
n = D.value;
((b.value = !0), (S.value = ``));
try {
let i = await r.post(`/product/${e}/config_option`, {
id: e,
config_options: {
...h.value,
promo_code: g.value,
event_promotion: ``,
},
qty: h.value.qty,
});
if (C || t !== T || n !== D.value) return;
let a = i.price_total ?? i.price;
if (a == null || !Number.isFinite(Number(a)) || Number(a) < 0)
throw Error(`未获得有效报价,请重新计算`);
((te.value = String(a)),
(_.value = Number(i.price_promo_code_discount ?? 0)),
(v.value = Number(i.price_client_level_discount ?? 0)),
(E.value = n));
} catch (e) {
!C &&
t === T &&
(S.value = e instanceof Error ? e.message : `报价加载失败,请重试`);
} finally {
!C && t === T && (b.value = !1);
}
}
async function fe() {
let t = ++w;
(k(), (y.value = !0), (S.value = ``), a && P());
try {
if (!(await I(t))) return;
if (
!l.value?.line.length ||
!l.value.node.length ||
!l.value.package.length
)
throw Error(`该商品暂无可售配置`);
if (!(await z(t))) return;
let n = await r.get(`/product/${e}/self_defined_field/order_page`);
if (C || t !== w) return;
if (!Array.isArray(n?.data))
throw Error(`商品自定义字段加载失败,请重试`);
if (
((m.value = product_fields_r(n)),
(p.value = product_fields_t(m.value)),
a && P(),
!(await de(t)))
)
return;
((y.value = !1), await B());
} catch (e) {
!C &&
t === w &&
(S.value = e instanceof Error ? e.message : `加载商品配置失败`);
} finally {
!C && t === w && (y.value = !1);
}
}
async function V(e = `simple`) {
// 线路或节点改变会同时失效套餐和镜像;普通资源变化只重取周期及价格。
let t = ++w;
(k(), (S.value = ``));
try {
if (e === `line`) {
if (
((h.value.node_id = ``),
(h.value.package_config_id = ``),
!(await I(t)) || !(await z(t)))
)
return;
} else if (e === `node`) {
if (((h.value.package_config_id = ``), !(await I(t)) || !(await z(t))))
return;
} else e === `package` && oe(A.value);
if (!(await de(t))) return;
await B();
} catch (e) {
!C &&
t === w &&
(S.value = e instanceof Error ? e.message : `配置报价加载失败,请重试`);
}
}
async function pe(e) {
// 独立服务器换型号尽量保留当前带宽,否则选该型号默认变体,再重新确认报价。
if (t !== `jy_dcim`) return !1;
let n = j.value.find((t) => t.key === e.key);
if (!n) return !1;
let r = Number(h.value.bandwidth),
i = n.variants.find((e) => Number(e.bw_size) === r) ?? n.package;
return (
(h.value.package_config_id = i.id),
(h.value.bandwidth = Number(i.bw_size) || 0),
await V(`package`),
!0
);
}
async function me(e) {
// 独立服务器带宽是套餐变体,不是可任意填写的额外数值。
if (t !== `jy_dcim`) return !1;
let n = j.value
.find((e) => e.variants.some((e) => F(e.id, h.value.package_config_id)))
?.variants.find((t) => Number(t.bw_size) === Number(e));
return n
? ((h.value.package_config_id = n.id),
(h.value.bandwidth = Number(n.bw_size) || 0),
await V(`package`),
!0)
: !1;
}
function he() {
let e = A.value;
!e ||
h.value.data_disk.length >= ae.value ||
(h.value.data_disk.push({
size: Number(e.data_disk_size),
type: ``,
}),
V());
}
function ge(e) {
e < 0 ||
e >= h.value.data_disk.length ||
(h.value.data_disk.splice(e, 1), V());
}
function _e() {
if (!ie.value) throw Error(`当前配置报价尚未确认,请等待或重新计算报价`);
}
function ve() {
return {
product_id: e,
config_options: {
...h.value,
},
qty: h.value.qty,
customfield: {
promo_code: g.value,
event_promotion: ``,
},
self_defined_field: {
...p.value,
},
};
}
async function ye() {
// 自定义字段校验和报价检查先于加购;购物车编辑借助统一保存器防止覆盖已变化的配置。
(_e(), product_fields_i(m.value, p.value));
let e = ve();
if (a) {
let t = D.value;
return s(e, () => !C && ie.value && t === D.value);
}
return r.post(`/cart`, e);
}
async function be() {
if (a) throw Error(`请先保存配置,再返回购物车结算`);
(_e(), product_fields_i(m.value, p.value));
let e = ve();
return r.post(`/product/settle`, e);
}
return {
page: l,
images: u,
cycles: f,
config: h,
selectedPackage: A,
hardwareModels: j,
dataDiskLimit: ae,
price: te,
promoCode: g,
promoDiscount: _,
levelDiscount: v,
customFields: p,
customFieldDefinitions: m,
loading: y,
priceLoading: b,
error: S,
quoteReady: ie,
init: fe,
refresh: V,
calcPrice: B,
selectHardwareModel: pe,
selectPhysicalBandwidth: me,
addDataDisk: he,
removeDataDisk: ge,
addToCart: ye,
buyNow: be,
};
}
var de = {
key: 1,
class: `panel config-load-error`,
},
B = {
key: 2,
class: `config-layout`,
},
fe = {
class: `config-options`,
},
V = {
class: `panel`,
},
pe = {
class: `jy-config-row`,
},
me = {
class: `jy-config-row`,
},
he = {
class: `panel`,
},
ge = {
class: `jy-config-row`,
},
_e = {
class: `jy-model-filters`,
},
ve = {
class: `jy-model-table-wrap`,
},
ye = {
class: `jy-model-table`,
},
be = [`onClick`],
xe = [`name`, `checked`, `disabled`, `aria-label`, `onChange`],
Se = {
class: `jy-model-name`,
},
Ce = {
key: 0,
},
we = {
key: 0,
class: `panel`,
},
Te = {
key: 0,
class: `jy-config-row`,
},
Ee = {
class: `jy-defense-options`,
role: `group`,
"aria-label": `带宽套餐档位`,
},
De = [`aria-pressed`, `aria-label`, `title`, `disabled`, `onClick`],
Oe = {
key: 1,
class: `jy-config-row`,
},
ke = {
class: `jy-config-row`,
},
Ae = [`for`],
je = {
class: `jy-resource-control`,
},
Me = [`aria-valuetext`, `min`, `max`, `step`, `value`, `disabled`],
Ne = {
class: `jy-config-row`,
},
Pe = {
class: `jy-defense-options`,
role: `group`,
"aria-label": `DDoS 防护峰值`,
},
Fe = [`aria-pressed`, `disabled`, `onClick`],
Ie = {
class: `panel`,
},
Le = {
class: `form-row`,
},
Re = {
class: `form-row`,
},
ze = {
class: `form-row`,
},
Be = {
key: 0,
class: `panel`,
},
Ve = {
class: `storage-system`,
},
He = {
class: `form-row`,
},
Ue = {
class: `storage-disks`,
},
We = {
key: 1,
class: `panel`,
},
Ge = {
key: 0,
class: `form-row`,
},
Ke = {
class: `form-row`,
},
qe = {
class: `form-row`,
},
Je = {
key: 2,
class: `panel`,
},
Ye = {
class: `section-title`,
},
Xe = {
class: `form-row`,
},
Ze = {
class: `form-row`,
},
Qe = {
class: `form-row`,
},
H = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `JyCloudConfig`,
props: {
productId: {},
module: {},
identityLocked: {
type: Boolean,
},
edit: {},
},
emits: [`settled`],
setup(o, { emit: ee }) {
let _ = o,
x = ee,
C = z(_.productId, _.module, {
edit: _.edit,
}),
{
page: O,
images: ne,
cycles: re,
config: M,
selectedPackage: N,
hardwareModels: F,
dataDiskLimit: I,
price: le,
promoCode: L,
promoDiscount: ue,
levelDiscount: R,
customFields: H,
customFieldDefinitions: $e,
loading: et,
priceLoading: tt,
error: nt,
quoteReady: rt,
} = C,
U = ref(null),
it = ref(``),
W = ref(``),
G,
K = computed(() => !!_.identityLocked || U.value !== null),
q = computed(() => _.module === `jy_dcim`),
at = computed(
() =>
rt.value &&
!K.value &&
!!M.value.duration_id &&
!!M.value.image_id,
),
J = computed(() => ne.value.filter((e) => e.image?.length)),
ot = computed({
get: () =>
J.value.find((e) =>
e.image.some(
(e) => String(e.id) === String(M.value.image_id),
),
)?.id ?? null,
set: (e) => {
let t = J.value.find((t) => t.id === e)?.image[0];
t && ((M.value.image_id = t.id), (M.value.image_name = t.name));
},
}),
st = computed(
() => J.value.find((e) => e.id === ot.value)?.image ?? [],
),
ct = computed(() =>
J.value
.flatMap((e) => e.image ?? [])
.find((e) => String(e.id) === String(M.value.image_id)),
);
function lt(e) {
let t = st.value.find((t) => String(t.id) === String(e));
t &&
((M.value.image_id = t.id),
(M.value.image_name = t.name),
C.refresh());
}
let Y = (e, t, n) => [
{
type: `step`,
min_value: e,
max_value: t,
step: n,
},
],
ut = computed(() =>
N.value
? Y(
N.value.system_disk_size,
N.value.system_disk_max,
N.value.system_disk_step,
)
: [],
),
dt = computed(() =>
N.value
? Y(
N.value.data_disk_size,
N.value.data_disk_max,
N.value.data_disk_step,
)
: [],
),
ft = computed(() =>
N.value
? Y(N.value.ip_size, N.value.ip_max, N.value.ip_step)
: [],
),
pt = computed(() =>
N.value
? Y(
N.value.defense_size,
N.value.defense_max,
N.value.defense_step,
)
: [],
),
X = ref(null),
Z = ref(null),
mt = computed(() =>
[
...new Set(
F.value
.map((e) => e.package.cpu_num)
.filter((e) => Number(e) > 0),
),
].map((e) => ({
label: `${e} 颗`,
value: Number(e),
})),
),
ht = computed(() =>
[
...new Set(
F.value
.filter(
(e) =>
X.value === null ||
Number(e.package.cpu_num) === X.value,
)
.map((e) => e.memory)
.filter((e) => e > 0),
),
]
.sort((e, t) => e - t)
.map((e) => ({
label: `${e} GB`,
value: e,
})),
),
gt = computed(() =>
F.value.filter(
(e) =>
(X.value === null || Number(e.package.cpu_num) === X.value) &&
(Z.value === null || e.memory === Z.value),
),
),
_t = computed(() =>
F.value.find((e) =>
e.variants.some(
(e) => String(e.id) === String(M.value.package_config_id),
),
),
),
Q = computed(() =>
[
...new Set(
(_t.value?.variants ?? [])
.map((e) => Number(e.bw_size))
.filter((e) => Number.isFinite(e) && e > 0),
),
].sort((e, t) => e - t),
),
vt = computed(() =>
[
...new Set(
F.value.flatMap((e) =>
e.variants
.map((e) => Number(e.bw_size))
.filter((e) => Number.isFinite(e) && e > 0),
),
),
]
.sort((e, t) => e - t)
.map((e) => ({
value: e,
available: Q.value.includes(e),
})),
),
yt = computed(() =>
Q.value.length > 1 && q.value
? Q.value.map((e) => ({
value: e,
}))
: N.value
? Y(N.value.bw_size, N.value.bw_max, N.value.bw_step)
: [],
),
$ = computed(() => {
let e = Math.max(0, Number(N.value?.ip_size) || 0);
return {
min: e,
max: Math.max(e, Number(N.value?.ip_max) || e),
step: Math.max(1, Number(N.value?.ip_step) || 1),
};
}),
bt = computed(() => {
if (!N.value) return [];
let e = Math.max(0, Number(N.value.defense_size) || 0),
t = Math.max(e, Number(N.value.defense_max) || e),
n = Math.max(1, Number(N.value.defense_step) || 1);
if (Math.ceil((t - e) / n) > 20) return [e];
let r = [];
for (let i = e; i <= t; i += n) r.push(i);
return r.length ? r : [e];
}),
xt = computed(() =>
re.value.map((e) => ({
value: e.id,
label: e.name,
})),
),
St = computed(() => [
{
label: `线路`,
value: M.value.line_name || `未选择`,
},
{
label: `节点`,
value: M.value.node_name || `未选择`,
},
{
label: q.value ? `型号` : `套餐`,
value: q.value
? _t.value?.name || M.value.package_name || `未选择`
: M.value.package_name || `未选择`,
},
{
label: `计算资源`,
value: q.value
? `${M.value.cpu_num} 颗处理器 / ${M.value.memory} GB 内存`
: `${M.value.cpu_num} 核 / ${M.value.memory} GB`,
},
{
label: `操作系统`,
value:
os_name_t(ct.value?.name ?? M.value.image_name) || `未选择`,
},
...(q.value
? [
{
label: `硬盘`,
value: _t.value?.disk || P(N.value?.disk_desc),
},
]
: [
{
label: `系统盘`,
value: `${M.value.system_disk.size} GB`,
},
...M.value.data_disk.map((e, t) => ({
label: `数据盘 ${t + 1}`,
value: `${e.size} GB`,
})),
]),
{
label: `带宽上限`,
value: `${M.value.bandwidth} Mbps`,
},
{
label: `IPv4 地址`,
value: `${M.value.ip_num} 个`,
},
{
label: `DDoS 防护`,
value: `${M.value.protect} Gbps`,
},
]);
function Ct(e) {
return e.variants.some(
(e) => String(e.id) === String(M.value.package_config_id),
);
}
function wt(e) {
K.value || Ct(e) || C.selectHardwareModel(e);
}
function Tt(e) {
!K.value && Q.value.includes(e) && C.selectPhysicalBandwidth(e);
}
function Et() {
q.value && Q.value.length > 1
? C.selectPhysicalBandwidth(Number(M.value.bandwidth))
: C.refresh();
}
function Dt() {
if (gt.value.some(Ct)) return;
let e = gt.value[0];
e && wt(e);
}
function Ot(e) {
((X.value = e === null || e === `` ? null : Number(e)),
Z.value !== null &&
!ht.value.some((e) => e.value === Z.value) &&
(Z.value = ht.value[0]?.value ?? null),
Dt());
}
function kt(e) {
((Z.value = e === null || e === `` ? null : Number(e)), Dt());
}
function At() {
q.value && ((X.value = null), (Z.value = null), Dt());
}
async function jt() {
(await C.refresh(`line`), At());
}
async function Mt() {
(await C.refresh(`node`), At());
}
function Nt(e) {
e !== null &&
Number.isFinite(e) &&
((M.value.ip_num = e), C.calcPrice());
}
function Pt(e) {
M.value.ip_num = Number(e.target.value);
}
function Ft(e) {
((M.value.protect = e), (M.value.defense = e), C.calcPrice());
}
async function It(e) {
// 组件只向父级发出结算结果;编辑成功返回购物车,普通加购显示短时确认。
if (at.value) {
((U.value = e), (it.value = ``), (W.value = ``), clearTimeout(G));
try {
if (e === `buy`) x(`settled`, await C.buyNow());
else {
if ((await C.addToCart(), _.edit)) {
await navigateTo(`/cart`);
return;
}
((W.value = `已加入购物车`),
(G = setTimeout(() => (W.value = ``), 4e3)));
}
} catch (e) {
it.value = e instanceof Error ? e.message : `提交失败,请重试`;
} finally {
U.value = null;
}
}
}
return (
onBeforeUnmount(() => clearTimeout(G)),
onMounted(() => C.init()),
(n, i) => {
let c = ConfigLoadingShell,
d = message,
ee = button,
b = ConfigChoiceGrid,
x = select,
ne = ConfigBandwidth,
re = inputnumber,
P = ConfigDiskCard,
F = ConfigDiskAdd,
z = ConfigResourceOption,
G = ProductCustomFields,
ct = ConfigCheckout;
return (
openBlock(),
createElementBlock(
`div`,
{
class: normalizeClass([
`config-page`,
{
"jy-dcim-config": unref(q),
},
]),
},
[
unref(et)
? (openBlock(),
createBlock(
c,
{
key: 0,
},
{
catalog: withCtx(() => [
renderSlot(
n.$slots,
`catalog`,
{
disabled: unref(U) !== null,
},
void 0,
!0,
),
]),
_: 3,
},
))
: unref(nt) && !unref(O)?.line?.length
? (openBlock(),
createElementBlock(`div`, de, [
renderSlot(
n.$slots,
`catalog`,
{
disabled: unref(U) !== null,
},
void 0,
!0,
),
createVNode(
d,
{
severity: `error`,
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(
toDisplayString(unref(nt)),
1,
),
]),
_: 1,
},
),
createVNode(
ee,
{
label: `重新加载配置`,
icon: `pi pi-refresh`,
severity: `secondary`,
outlined: ``,
disabled: o.identityLocked,
onClick: (i[0] ||= (e) => unref(C).init()),
},
null,
8,
[`disabled`],
),
]))
: unref(O)
? (openBlock(),
createElementBlock(`div`, B, [
createElementVNode(`div`, fe, [
renderSlot(
n.$slots,
`catalog`,
{
disabled: unref(U) !== null,
},
void 0,
!0,
),
unref(q)
? (openBlock(),
createElementBlock(
Fragment,
{
key: 0,
},
[
createElementVNode(`section`, V, [
(i[35] ||= createElementVNode(
`h2`,
{
class: `section-title`,
},
`基础配置`,
-1,
)),
createElementVNode(`div`, pe, [
(i[33] ||= createElementVNode(
`label`,
null,
`区域`,
-1,
)),
createVNode(
b,
{
modelValue: unref(M).line_id,
"onUpdate:modelValue": (i[1] ||=
(e) =>
(unref(M).line_id = e)),
label: `区域`,
compact: ``,
disabled: unref(K),
options: unref(O).line.map(
(e) => ({
label: e.name,
value: e.id,
}),
),
onChange: jt,
},
null,
8,
[
`modelValue`,
`disabled`,
`options`,
],
),
]),
createElementVNode(`div`, me, [
(i[34] ||= createElementVNode(
`label`,
null,
`可用区`,
-1,
)),
createVNode(
b,
{
modelValue: unref(M).node_id,
"onUpdate:modelValue": (i[2] ||=
(e) =>
(unref(M).node_id = e)),
label: `可用区`,
compact: ``,
disabled: unref(K),
options: unref(O).node.map(
(e) => ({
label: e.name,
value: e.id,
}),
),
onChange: Mt,
},
null,
8,
[
`modelValue`,
`disabled`,
`options`,
],
),
]),
]),
createElementVNode(`section`, he, [
(i[39] ||= createElementVNode(
`h2`,
{
class: `section-title`,
},
`机型配置`,
-1,
)),
createElementVNode(`div`, ge, [
(i[36] ||= createElementVNode(
`span`,
null,
`规格`,
-1,
)),
createElementVNode(`div`, _e, [
createVNode(
x,
{
"model-value": unref(X),
"aria-label": `筛选处理器数量`,
options: unref(mt),
"option-label": `label`,
"option-value": `value`,
placeholder: `请选择处理器数量`,
disabled: unref(K),
"onUpdate:modelValue": Ot,
},
null,
8,
[
`model-value`,
`options`,
`disabled`,
],
),
createVNode(
x,
{
"model-value": unref(Z),
"aria-label": `筛选内存`,
options: unref(ht),
"option-label": `label`,
"option-value": `value`,
placeholder: `请选择内存`,
disabled:
unref(K) ||
!unref(ht).length,
"onUpdate:modelValue": kt,
},
null,
8,
[
`model-value`,
`options`,
`disabled`,
],
),
]),
]),
createElementVNode(`div`, ve, [
createElementVNode(`table`, ye, [
(i[38] ||= createElementVNode(
`thead`,
null,
[
createElementVNode(
`tr`,
null,
[
createElementVNode(
`th`,
{
scope: `col`,
},
[
createElementVNode(
`span`,
{
class: `sr-only`,
},
`选择`,
),
],
),
createElementVNode(
`th`,
{
scope: `col`,
},
`型号`,
),
createElementVNode(
`th`,
{
scope: `col`,
},
`处理器数量`,
),
createElementVNode(
`th`,
{
scope: `col`,
},
`内存`,
),
createElementVNode(
`th`,
{
scope: `col`,
},
`硬盘`,
),
],
),
],
-1,
)),
createElementVNode(
`tbody`,
null,
[
(openBlock(!0),
createElementBlock(
Fragment,
null,
renderList(
unref(gt),
(t) => (
openBlock(),
createElementBlock(
`tr`,
{
key: t.key,
class:
normalizeClass({
selected: Ct(t),
}),
onClick: (e) =>
wt(t),
},
[
createElementVNode(
`td`,
null,
[
createElementVNode(
`input`,
{
type: `radio`,
name: `jy-dcim-model-${o.productId}`,
checked:
Ct(t),
disabled:
unref(K),
"aria-label": `选择 ${t.name}`,
onChange: (
e,
) => wt(t),
},
null,
40,
xe,
),
],
),
createElementVNode(
`td`,
Se,
toDisplayString(
t.name,
),
1,
),
createElementVNode(
`td`,
null,
toDisplayString(
t.processorParameters,
),
1,
),
createElementVNode(
`td`,
null,
toDisplayString(
t.memory,
) + ` GB`,
1,
),
createElementVNode(
`td`,
null,
toDisplayString(
t.disk,
),
1,
),
],
10,
be,
)
),
),
128,
)),
unref(gt).length
? createCommentVNode(``, !0)
: (openBlock(),
createElementBlock(
`tr`,
Ce,
[
...(i[37] ||= [
createElementVNode(
`td`,
{
colspan: `5`,
class: `jy-no-model`,
},
`没有符合当前筛选条件的型号。`,
-1,
),
]),
],
)),
],
),
]),
]),
]),
unref(N)
? (openBlock(),
createElementBlock(`section`, we, [
(i[43] ||= createElementVNode(
`h2`,
{
class: `section-title`,
},
`网络配置`,
-1,
)),
unref(vt).length > 1
? (openBlock(),
createElementBlock(
`div`,
Te,
[
(i[40] ||=
createElementVNode(
`span`,
null,
`带宽套餐`,
-1,
)),
createElementVNode(
`div`,
Ee,
[
(openBlock(!0),
createElementBlock(
Fragment,
null,
renderList(
unref(vt),
(t) => (
openBlock(),
createElementBlock(
`button`,
{
key: t.value,
type: `button`,
class:
normalizeClass(
{
active:
Number(
unref(
M,
)
.bandwidth,
) ===
t.value &&
t.available,
},
),
"aria-pressed":
Number(
unref(M)
.bandwidth,
) ===
t.value &&
t.available,
"aria-label": `${t.value}M 套餐${t.available ? `` : `,当前机型不可选`}`,
title:
t.available
? `选择 ${t.value}M 套餐`
: `当前机型暂无此档位`,
disabled:
unref(
K,
) ||
!t.available,
onClick: (
e,
) =>
Tt(
t.value,
),
},
toDisplayString(
t.value,
) + `M`,
11,
De,
)
),
),
128,
)),
],
),
],
))
: createCommentVNode(``, !0),
unref(N).bw_status
? (openBlock(),
createElementBlock(
`div`,
Oe,
[
(i[41] ||=
createElementVNode(
`label`,
null,
`带宽`,
-1,
)),
createVNode(
ne,
{
modelValue:
unref(M).bandwidth,
"onUpdate:modelValue":
(i[3] ||= (e) =>
(unref(
M,
).bandwidth = e)),
disabled: unref(K),
options: unref(yt),
onChange: Et,
},
null,
8,
[
`modelValue`,
`disabled`,
`options`,
],
),
],
))
: createCommentVNode(``, !0),
createElementVNode(`div`, ke, [
createElementVNode(
`label`,
{
for: `jy-ip-count-${o.productId}`,
},
`公网 IP`,
8,
Ae,
),
createElementVNode(`div`, je, [
createVNode(
re,
{
"input-id": `jy-ip-count-${o.productId}`,
"model-value": Number(
unref(M).ip_num,
),
min: unref($).min,
max: unref($).max,
step: unref($).step,
suffix: ` 个`,
"show-buttons": ``,
"button-layout": `horizontal`,
disabled:
unref(K) ||
unref($).min ===
unref($).max,
"onUpdate:modelValue": Nt,
},
null,
8,
[
`input-id`,
`model-value`,
`min`,
`max`,
`step`,
`disabled`,
],
),
createElementVNode(
`input`,
{
class: `jy-resource-slider`,
type: `range`,
"aria-label": `公网 IPv4 地址数量`,
"aria-valuetext": `${unref(M).ip_num} 个 IPv4 地址`,
min: unref($).min,
max: unref($).max,
step: unref($).step,
value: unref(M).ip_num,
disabled:
unref(K) ||
unref($).min ===
unref($).max,
onInput: Pt,
onChange: (i[4] ||= (e) =>
unref(C).calcPrice()),
},
null,
40,
Me,
),
createElementVNode(
`small`,
null,
toDisplayString(
unref($).min,
) +
`–` +
toDisplayString(
unref($).max,
) +
` 个 IPv4 地址`,
1,
),
]),
]),
createElementVNode(`div`, Ne, [
(i[42] ||= createElementVNode(
`span`,
null,
`防御`,
-1,
)),
createElementVNode(`div`, Pe, [
(openBlock(!0),
createElementBlock(
Fragment,
null,
renderList(
unref(bt),
(t) => (
openBlock(),
createElementBlock(
`button`,
{
key: t,
type: `button`,
class:
normalizeClass({
active:
Number(
unref(M)
.protect,
) === t,
}),
"aria-pressed":
Number(
unref(M)
.protect,
) === t,
disabled: unref(K),
onClick: (e) =>
Ft(t),
},
toDisplayString(t) +
` Gbps`,
11,
Fe,
)
),
),
128,
)),
]),
]),
]))
: createCommentVNode(``, !0),
],
64,
))
: (openBlock(),
createElementBlock(
Fragment,
{
key: 1,
},
[
createElementVNode(`section`, Ie, [
(i[47] ||= createElementVNode(
`h2`,
{
class: `section-title`,
},
`基础配置`,
-1,
)),
createElementVNode(`div`, Le, [
(i[44] ||= createElementVNode(
`label`,
null,
`线路`,
-1,
)),
createVNode(
b,
{
modelValue: unref(M).line_id,
"onUpdate:modelValue": (i[5] ||=
(e) =>
(unref(M).line_id = e)),
label: `线路`,
disabled: unref(K),
options: unref(O).line.map(
(e) => ({
label: e.name,
value: e.id,
}),
),
onChange: (i[6] ||= (e) =>
unref(C).refresh(`line`)),
},
null,
8,
[
`modelValue`,
`disabled`,
`options`,
],
),
]),
createElementVNode(`div`, Re, [
(i[45] ||= createElementVNode(
`label`,
null,
`节点`,
-1,
)),
createVNode(
b,
{
modelValue: unref(M).node_id,
"onUpdate:modelValue": (i[7] ||=
(e) =>
(unref(M).node_id = e)),
label: `节点`,
disabled: unref(K),
options: unref(O).node.map(
(e) => ({
label: e.name,
value: e.id,
}),
),
onChange: (i[8] ||= (e) =>
unref(C).refresh(`node`)),
},
null,
8,
[
`modelValue`,
`disabled`,
`options`,
],
),
]),
createElementVNode(`div`, ze, [
(i[46] ||= createElementVNode(
`label`,
null,
`套餐`,
-1,
)),
createVNode(
b,
{
modelValue:
unref(M).package_config_id,
"onUpdate:modelValue": (i[9] ||=
(e) =>
(unref(
M,
).package_config_id = e)),
label: `套餐`,
disabled: unref(K),
options: unref(O).package.map(
(e) => ({
label: `${e.name} · ${e.cpu_num}核 ${e.memory}GB`,
value: e.id,
}),
),
onChange: (i[10] ||= (e) =>
unref(C).refresh(`package`)),
},
null,
8,
[
`modelValue`,
`disabled`,
`options`,
],
),
]),
]),
unref(N)
? (openBlock(),
createElementBlock(`section`, Be, [
(i[49] ||= createElementVNode(
`h2`,
{
class: `section-title`,
},
`存储配置`,
-1,
)),
createElementVNode(`div`, Ve, [
createVNode(
P,
{
modelValue:
unref(M).system_disk.size,
"onUpdate:modelValue":
(i[11] ||= (e) =>
(unref(
M,
).system_disk.size =
e)),
label: `系统盘`,
title: `系统盘`,
disabled: unref(K),
options: unref(ut),
onChange: (i[12] ||= (e) =>
unref(C).refresh()),
},
null,
8,
[
`modelValue`,
`disabled`,
`options`,
],
),
]),
createElementVNode(`div`, He, [
(i[48] ||= createElementVNode(
`label`,
null,
`数据盘`,
-1,
)),
createElementVNode(`div`, Ue, [
(openBlock(!0),
createElementBlock(
Fragment,
null,
renderList(
unref(M).data_disk,
(e, t) => (
openBlock(),
createBlock(
P,
{
key: t,
modelValue: e.size,
"onUpdate:modelValue":
(t) =>
(e.size = t),
label: `数据盘 ${t + 1}`,
"hide-label": ``,
title: `数据盘`,
removable: ``,
disabled: unref(K),
options: unref(dt),
onChange: (i[13] ||=
(e) =>
unref(
C,
).refresh()),
onRemove: (e) =>
unref(
C,
).removeDataDisk(
t,
),
},
null,
8,
[
`modelValue`,
`onUpdate:modelValue`,
`label`,
`disabled`,
`options`,
`onRemove`,
],
)
),
),
128,
)),
unref(M).data_disk.length <
unref(I)
? (openBlock(),
createBlock(
F,
{
key: 0,
disabled: unref(K),
onAdd: (i[14] ||= (
e,
) =>
unref(
C,
).addDataDisk()),
},
null,
8,
[`disabled`],
))
: createCommentVNode(
``,
!0,
),
]),
]),
]))
: createCommentVNode(``, !0),
unref(N)
? (openBlock(),
createElementBlock(`section`, We, [
(i[52] ||= createElementVNode(
`h2`,
{
class: `section-title`,
},
`网络配置`,
-1,
)),
unref(N).bw_status
? (openBlock(),
createElementBlock(
`div`,
Ge,
[
createVNode(
ne,
{
modelValue:
unref(M).bandwidth,
"onUpdate:modelValue":
(i[15] ||= (e) =>
(unref(
M,
).bandwidth = e)),
disabled: unref(K),
options: unref(yt),
onChange: (i[16] ||= (
e,
) =>
unref(C).refresh()),
},
null,
8,
[
`modelValue`,
`disabled`,
`options`,
],
),
],
))
: createCommentVNode(``, !0),
createElementVNode(`div`, Ke, [
(i[50] ||= createElementVNode(
`label`,
null,
`IPv4 地址`,
-1,
)),
createVNode(
z,
{
modelValue: unref(M).ip_num,
"onUpdate:modelValue":
(i[17] ||= (e) =>
(unref(M).ip_num = e)),
label: `IPv4 地址`,
unit: `个`,
disabled: unref(K),
options: unref(ft),
onChange: (i[18] ||= (e) =>
unref(C).refresh()),
},
null,
8,
[
`modelValue`,
`disabled`,
`options`,
],
),
]),
createElementVNode(`div`, qe, [
(i[51] ||= createElementVNode(
`label`,
null,
`DDoS 防护`,
-1,
)),
createVNode(
z,
{
modelValue:
unref(M).protect,
"onUpdate:modelValue":
(i[19] ||= (e) =>
(unref(M).protect = e)),
label: `DDoS 防护`,
unit: `Gbps`,
disabled: unref(K),
options: unref(pt),
onChange: (i[20] ||= (e) =>
unref(C).refresh()),
},
null,
8,
[
`modelValue`,
`disabled`,
`options`,
],
),
]),
]))
: createCommentVNode(``, !0),
],
64,
)),
unref(J).length
? (openBlock(),
createElementBlock(`section`, Je, [
createElementVNode(
`h2`,
Ye,
toDisplayString(
unref(q) ? `系统配置` : `操作系统`,
),
1,
),
createVNode(
b,
{
modelValue: unref(ot),
"onUpdate:modelValue": (i[21] ||= (
e,
) =>
isRef(ot) ? (ot.value = e) : null),
label: `操作系统`,
images: ``,
disabled: unref(K),
options: unref(J).map((e) => ({
label: unref(os_name_t)(e.name),
value: e.id,
iconUrl: e.icon_url,
icon: e.icon,
})),
onChange: (i[22] ||= (e) =>
unref(C).refresh()),
},
null,
8,
[`modelValue`, `disabled`, `options`],
),
createElementVNode(`div`, Xe, [
(i[53] ||= createElementVNode(
`label`,
null,
`镜像版本`,
-1,
)),
createVNode(
x,
{
"model-value": unref(M).image_id,
"aria-label": `镜像版本`,
disabled: unref(K),
options: unref(st),
"option-label": (e) =>
unref(os_name_t)(e.name),
"option-value": `id`,
class: `grow`,
"onUpdate:modelValue": lt,
},
null,
8,
[
`model-value`,
`disabled`,
`options`,
`option-label`,
],
),
]),
]))
: createCommentVNode(``, !0),
]),
createVNode(
G,
{
modelValue: unref(H),
"onUpdate:modelValue": (i[23] ||= (e) =>
isRef(H) ? (H.value = e) : null),
fields: unref($e),
disabled: unref(K),
},
null,
8,
[`modelValue`, `fields`, `disabled`],
),
createVNode(
ct,
{
"product-id": _.productId,
quantity: unref(M).qty,
"edit-position": _.edit?.position,
editing: !!o.edit,
summary: unref(St),
price: unref(le),
"quote-ready": unref(rt) && !o.identityLocked,
"price-loading": unref(tt),
"can-submit": unref(at),
"active-action": unref(U),
disabled: unref(K),
"promo-code": unref(L),
"onUpdate:promoCode": (i[28] ||= (e) =>
isRef(L) ? (L.value = e) : null),
"promo-discount": unref(ue),
"level-discount": unref(R),
error: unref(nt),
"action-error": unref(it),
"cart-tip": unref(W),
onCart: (i[29] ||= (e) => It(`cart`)),
onBuy: (i[30] ||= (e) => It(`buy`)),
onRecalc: (i[31] ||= (e) =>
unref(C).calcPrice()),
onRetry: (i[32] ||= (e) =>
unref(C).refresh()),
},
{
default: withCtx(() => [
createElementVNode(`div`, Ze, [
(i[54] ||= createElementVNode(
`label`,
null,
`购买时长`,
-1,
)),
createVNode(
x,
{
modelValue: unref(M).duration_id,
"onUpdate:modelValue": (i[24] ||= (
e,
) => (unref(M).duration_id = e)),
"aria-label": `购买时长`,
disabled: unref(K),
options: unref(xt),
"option-label": `label`,
"option-value": `value`,
class: `grow`,
onChange: (i[25] ||= (e) =>
unref(C).refresh()),
},
null,
8,
[`modelValue`, `disabled`, `options`],
),
]),
createElementVNode(`div`, Qe, [
(i[55] ||= createElementVNode(
`label`,
null,
`购买数量`,
-1,
)),
createVNode(
re,
{
modelValue: unref(M).qty,
"onUpdate:modelValue": [
(i[26] ||= (e) =>
(unref(M).qty = e)),
(i[27] ||= (e) =>
unref(C).calcPrice()),
],
"aria-label": `购买数量`,
disabled: unref(K),
min: 1,
max: 99,
"show-buttons": ``,
"button-layout": `horizontal`,
},
null,
8,
[`modelValue`, `disabled`],
),
]),
]),
_: 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),
],
2,
)
);
}
);
},
}),
[[`__scopeId`, `data-v-7837d303`]],
),
{
__name: `JyCloudConfig`,
},
);
export {};
export default H;
</script>