Files
console-dev/app/components/config/MfDcimConfig.vue
T

2058 lines
89 KiB
Vue

<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/MfDcimConfig.BhC_eZ0V.css";
import { toDisplayString } from "vue";
import { renderList } from "vue";
import { onMounted } from "vue";
import { useId } from "vue";
import { normalizeClass } from "vue";
import { onBeforeUnmount } 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 { 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 { useRoute } from "#app";
import { navigateTo } from "#app";
import { NuxtLink } from "#components";
import { useApi } from "~/lib/auth.js";
import { t as useSiteConfig_t } from "~/lib/useSiteConfig.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 checkbox from "primevue/checkbox";
import textarea from "primevue/textarea";
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 { o as cart_edit_o } from "~/lib/cart-edit.js";
import { r as cart_edit_r } from "~/lib/cart-edit.js";
import ConfigDiskCard from "~/components/config/ConfigDiskCard.vue";
import slider from "primevue/slider";
import { productStock } from "~/lib/product-inventory.js";
import { resourceOptionValue } from "~/lib/resource-option-value.js";
function z(e, t = {}, n = `mf_dcim`, r = {}) {
// 商品库存与型号同步库存可能同时生效;可购数量取所有有效限制中的最小值。
let i = useApi(),
s = r.edit,
l = ref(!s),
u = cart_edit_r(i, s),
f = `/product/${e}/${n}`,
p = t.product,
m = ref(null),
h = ref(null),
g = ref([]),
_ = ref(null),
v = ref([]),
y = ref(!0),
b = ref(!1),
x = ref(``),
S = ref(`—`),
C = ref(1),
w = ref(``),
te = ref(0),
T = ref(0),
E = ref(!1),
D = ref({
data_center_id: 0,
line_id: 0,
model_config_id: 0,
image_id: 0,
duration_id: 0,
bw: ``,
flow: ``,
ip_num: ``,
peak_defence: 0,
optional_memory: {},
optional_disk: {},
optional_gpu: {},
notes: ``,
auto_renew: 0,
}),
O = ref({}),
k = ref([]),
A = computed(() =>
(h.value?.data_center ?? []).flatMap((e) =>
(e.city ?? []).flatMap((t) =>
(t.area ?? []).flatMap((n) =>
(n.line ?? []).map((r) => ({
...r,
location: [t.name, n.name].filter(Boolean).join(` / `),
country: e.name,
})),
),
),
),
),
j = computed(() =>
h.value?.model_config.find((e) => e.id === D.value.model_config_id),
),
ne = computed(() => A.value.find((e) => e.id === D.value.line_id)),
re = computed(() => productStock(m.value, j.value)),
ie = computed(() => re.value === null || C.value <= re.value),
F = computed(() =>
JSON.stringify({
config: D.value,
qty: C.value,
promo: w.value,
fields: O.value,
}),
),
L = ref(``),
R = ref(0),
z = 0,
B = 0,
se = 0,
V = !1,
H = !1,
U = 0,
W = null,
ce = computed(() => !!_.value && R.value === D.value.line_id),
G = computed(
() =>
l.value &&
!V &&
!b.value &&
ce.value &&
ie.value &&
!!L.value &&
L.value === F.value,
);
function K() {
(se++,
(L.value = ``),
(S.value = `—`),
(te.value = 0),
(T.value = 0),
(b.value = !1));
}
(watch(F, K, {
flush: `sync`,
}),
watch(
() => D.value.line_id,
() => {
((R.value = 0),
(_.value = null),
H || ((D.value.duration_id = 0), (U = 0)),
(v.value = []));
},
{
flush: `sync`,
},
),
watch(
() => D.value.model_config_id,
() => {
H ||
((D.value.optional_memory = {}),
(D.value.optional_disk = {}),
(D.value.optional_gpu = {}));
},
{
flush: `sync`,
},
),
onBeforeUnmount(() => {
((V = !0), B++, z++, K());
}));
let q = (e) => !V && e === z,
le = (e) => {
const value = resourceOptionValue(e?.[0]);
return value === undefined ? `` : String(value);
};
function ue() {
// 报价和提交共用前置校验,型号/线路/镜像与正整数数量缺一不可。
if (!j.value || !ne.value || !D.value.image_id)
throw Error(`请选择型号、线路和操作系统`);
if (!Number.isInteger(C.value) || C.value < 1)
throw Error(`购买数量必须为正整数`);
if (!ie.value) throw Error(`所选型号库存不足,请减少数量或选择其他型号`);
}
async function de(e) {
// 网络档位来自线路详情;回填购物车时验证旧档位仍合法,不静默替用户换配置。
let t = D.value.line_id;
if (ce.value) return !0;
(!W || W.id !== t) &&
(W = {
id: t,
promise: i.get(`${f}/line/${t}`),
});
let n = W;
try {
let r = await n.promise;
if (!q(e) || t !== D.value.line_id) return !1;
if (((_.value = r), U === t)) {
let e = (e, t) =>
e?.some((e) => {
let n = Number(t);
if (t === `` || t == null || !Number.isFinite(n)) return !1;
if (e.type !== `step` && e.type !== `total`)
return n === Number(e.value);
let r = Number(e.min_value ?? e.value),
i = Number(e.max_value ?? e.value),
a = Number(e.step) || 1;
return (
n >= r &&
n <= i &&
Math.abs((n - r) / a - Math.round((n - r) / a)) < 1e-7
);
});
if (
(r.bill_type === `bw` && r.bw?.length && !e(r.bw, D.value.bw)) ||
(r.bill_type === `flow` &&
r.flow?.length &&
!e(r.flow, D.value.flow)) ||
(r.ip?.length && !e(r.ip, D.value.ip_num)) ||
(r.defence?.length && !e(r.defence, D.value.peak_defence))
)
throw Error(`购物车中的网络配置已不可用,请调整后重新获取报价`);
U = 0;
} else
((D.value.bw = r.bill_type === `bw` ? le(r.bw) : ``),
(D.value.flow = r.bill_type === `flow` ? le(r.flow) : ``),
(D.value.ip_num = le(r.ip)),
(D.value.peak_defence = Number(
r.order_default_defence ?? r.defence?.[0]?.value ?? 0,
)));
return ((R.value = t), !0);
} finally {
W === n && (W = null);
}
}
function fe() {
return {
...JSON.parse(JSON.stringify(D.value)),
promo_code: w.value,
event_promotion: ``,
};
}
function pe(e) {
// 回填期间 H 暂停“切换型号即清空选配”的 watch,防止用户原有选配被初始化误删。
let t =
e.config_options &&
typeof e.config_options == `object` &&
!Array.isArray(e.config_options)
? cart_edit_n(e.config_options)
: {};
H = !0;
try {
((D.value = {
...D.value,
...t,
model_config_id: Number(t.model_config_id ?? D.value.model_config_id),
line_id: Number(t.line_id ?? D.value.line_id),
data_center_id: Number(t.data_center_id ?? D.value.data_center_id),
image_id: Number(t.image_id ?? D.value.image_id),
duration_id: Number(t.duration_id ?? t.cycle ?? D.value.duration_id),
}),
(U = D.value.line_id));
} finally {
H = !1;
}
let n = Number(e.qty);
Number.isInteger(n) && n > 0 && (C.value = n);
let r =
e.customfield &&
typeof e.customfield == `object` &&
!Array.isArray(e.customfield)
? e.customfield
: {},
i = t.promo_code ?? r.promo_code;
Array.isArray(i)
? (w.value = String(i.find(Boolean) ?? ``))
: i != null && (w.value = String(i));
let a =
e.self_defined_field &&
typeof e.self_defined_field == `object` &&
!Array.isArray(e.self_defined_field)
? e.self_defined_field
: {};
for (let e of k.value) O.value[e.id] = String(a[e.id] ?? ``);
}
async function me(t) {
// 报价响应必须同时匹配配置代次、请求序号和快照,且金额必须为有效非负数。
if (!l.value) return;
let n = ++se,
r = F.value;
b.value = !0;
let a = () => q(t) && n === se && r === F.value;
try {
let t = await i.post(`/product/${e}/config_option`, {
config_options: fe(),
qty: C.value,
});
if (!a()) return;
let n = t.price_total;
if (
n == null ||
String(n).trim() === `` ||
!Number.isFinite(Number(n)) ||
Number(n) < 0
)
throw Error(`未获得有效报价,请重新计算`);
((S.value = Number(n).toFixed(2)),
(te.value = Number(t.price_promo_code_discount ?? 0)),
(T.value = Number(t.price_client_level_discount ?? 0)),
(L.value = r));
} catch (e) {
a() && (x.value = e instanceof Error ? e.message : `报价加载失败`);
} finally {
a() && (b.value = !1);
}
}
async function he() {
// 型号/网络变化先重新确定可售周期,再报价;无可购周期不能继续显示旧报价。
let e = ++z;
(K(), (x.value = ``), (b.value = !0));
try {
if ((ue(), !(await de(e)))) return;
let t = F.value,
n = await i.post(`${f}/duration`, {
...JSON.parse(JSON.stringify(D.value)),
});
if (!q(e) || t !== F.value) return;
if (
((v.value = (Array.isArray(n) ? n : n?.id ? [n] : []).filter(
(e) => Number(e.id) > 0,
)),
!v.value.length)
)
throw Error(`当前配置没有可购买周期,请调整配置`);
(v.value.some((e) => e.id === D.value.duration_id) ||
(D.value.duration_id = (
v.value.find((e) => e.is_default === 1) ?? v.value[0]
).id),
q(e) && ((y.value = !1), await me(e)));
} catch (t) {
q(e) && (x.value = t instanceof Error ? t.message : `加载配置报价失败`);
} finally {
q(e) && (b.value = !1);
}
}
async function ge() {
if (!ce.value || !v.value.some((e) => e.id === D.value.duration_id)) {
await he();
return;
}
let e = ++z;
(K(), (x.value = ``));
try {
(ue(), await me(e));
} catch (t) {
q(e) && (x.value = t instanceof Error ? t.message : `报价加载失败`);
}
}
async function _e() {
l.value = !1;
let n = ++B;
(z++,
K(),
(y.value = !0),
(x.value = ``),
(h.value = null),
(m.value = null),
(_.value = null),
(R.value = 0),
(W = null),
(g.value = []),
(v.value = []));
try {
let a = p
? Promise.resolve({
product: p,
})
: i.get(`/product/${e}`);
p = void 0;
let [o, c, u] = await Promise.all([
i.get(`${f}/order_page`),
i.get(`${f}/image`),
a,
]);
if (V || n !== B) return;
let d = u?.product ?? u;
if (!d || Number(d.id) !== Number(e) || d.hidden === 1)
throw Error(`商品不存在或已下架`);
if (
((m.value = d),
(h.value = o),
(g.value = c.list ?? []),
(k.value = []),
(O.value = {}),
r.customFields || s)
) {
let t = await i.get(`/product/${e}/self_defined_field/order_page`);
if (V || n !== B) return;
if (!Array.isArray(t?.data))
throw Error(`商品自定义字段加载失败,请重试`);
((k.value = product_fields_r(t)),
(O.value = product_fields_t(k.value)));
}
let _ = t.modelId
? o.model_config.find((e) => e.id === t.modelId)
: o.model_config[0],
v = t.lineId ? A.value.find((e) => e.id === t.lineId) : A.value[0];
if (!_ || !v)
throw Error(`所选型号或线路已不可用,请返回物理服务器列表重新选择`);
((D.value.model_config_id = _.id),
(D.value.line_id = v.id),
(D.value.data_center_id = v.data_center_id),
(D.value.image_id = g.value.flatMap((e) => e.image ?? [])[0]?.id ?? 0),
cart_edit_o(
s,
k.value.map((e) => e.id),
),
s && pe(s.item),
(l.value = !0),
await he());
} catch (e) {
!V &&
n === B &&
((h.value = null),
(x.value = e instanceof Error ? e.message : `加载物理服务器配置失败`));
} finally {
!V && n === B && (y.value = !1);
}
}
async function ve(t) {
// 最终提交前调用 validate_settle,再检查配置未变化;正在提交的状态阻止重复下单。
if (s && t !== `cart`) throw Error(`请先保存配置,再返回购物车结算`);
if (E.value) throw Error(`正在提交,请勿重复操作`);
if ((ue(), product_fields_i(k.value, O.value), !G.value))
throw Error(`当前配置报价尚未确认,请重新计算`);
E.value = !0;
let n = F.value,
r = fe(),
a = C.value;
try {
if (
(await i.post(`${f}/validate_settle`, {
custom: r,
}),
V || n !== F.value || !G.value)
)
throw Error(`配置已改变,请重新确认报价后提交`);
let o = Object.keys(O.value).length
? {
...O.value,
}
: [],
c = {
product_id: e,
config_options: r,
qty: a,
customfield: {
promo_code: w.value,
event_promotion: ``,
},
self_defined_field: o,
};
if (t === `cart` && s)
return await u(c, () => !V && G.value && n === F.value);
let l = await i.post(t === `cart` ? `/cart` : `/product/settle`, c);
return (K(), l);
} finally {
E.value = !1;
}
}
return {
product: m,
orderPage: h,
images: g,
lineDetail: _,
cycles: v,
config: D,
customFields: O,
customFieldDefinitions: k,
qty: C,
price: S,
loading: y,
priceLoading: b,
error: x,
quoteReady: G,
promoCode: w,
promoDiscount: te,
levelDiscount: T,
submitting: E,
lines: A,
model: j,
selectedLine: ne,
stock: re,
available: ie,
init: _e,
refresh: he,
calcPrice: ge,
addToCart: () => ve(`cart`),
buyNow: () => ve(`buy`),
};
}
var B = {
class: `config-page dcim-config`,
},
se = {
key: 1,
class: `panel config-load-error`,
},
V = {
key: 2,
class: `config-layout`,
},
H = {
class: `config-options`,
},
U = {
class: `panel`,
},
W = {
class: `dcim-base`,
},
ce = {
class: `base-specs`,
},
G = {
key: 0,
class: `config-change`,
},
K = {
class: `config-change-fields`,
},
q = {
key: 0,
class: `form-row`,
},
le = [`id`],
ue = {
key: 1,
class: `form-row`,
},
de = [`id`],
fe = {
key: 0,
class: `panel`,
},
pe = {
class: `storage-grid`,
},
me = {
class: `disk-quantity`,
},
he = [`for`],
ge = {
class: `panel`,
},
_e = [`id`, `for`],
ve = [`aria-labelledby`],
ye = [`aria-pressed`, `disabled`, `onClick`],
be = {
key: 0,
class: `form-row`,
},
xe = [`id`],
Se = [`aria-labelledby`],
Ce = [`aria-pressed`, `disabled`, `onClick`],
we = {
key: 1,
class: `panel`,
},
Te = [`for`],
Ee = {
class: `panel`,
},
De = {
class: `form-row`,
},
Oe = [`id`],
ke = {
key: 0,
class: `image-charge`,
},
Ae = {
class: `panel`,
},
je = {
class: `form-row`,
},
Me = [`for`],
Ne = {
class: `form-row`,
},
Pe = [`id`],
Fe = {
class: `form-row`,
},
Ie = [`for`],
Le = {
key: 0,
class: `stock-hint`,
},
Re = {
class: `agreement`,
},
ze = [`for`],
Be = {
key: 0,
class: `agreement`,
},
Ve = [`for`],
He = [`href`],
J = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `MfDcimConfig`,
props: {
productId: {},
module: {
default: `mf_dcim`,
},
initialProduct: {},
edit: {},
},
emits: [`settled`],
setup(a, { emit: o }) {
let v = a,
ee = o,
T = useRoute(),
M = useId(),
N = z(
v.productId,
{
modelId: Number(T.query.model_id) || void 0,
lineId: Number(T.query.line_id) || void 0,
product: v.initialProduct,
},
v.module,
{
customFields: !0,
edit: v.edit,
},
),
{
orderPage: P,
images: ae,
lineDetail: I,
cycles: oe,
config: J,
customFields: Ue,
customFieldDefinitions: We,
qty: Ge,
price: Ke,
loading: qe,
priceLoading: Je,
error: Ye,
quoteReady: Xe,
promoCode: Ze,
promoDiscount: Qe,
levelDiscount: $e,
submitting: Y,
lines: et,
model: X,
selectedLine: Z,
stock: Q,
} = N,
tt = useSiteConfig_t(),
nt = computed(() => {
let e = tt.config.value?.terms_service_url;
return typeof e == `string` && /^https?:\/\//i.test(e) ? e : ``;
}),
rt = ref(!1),
it = ref(null),
at = ref(``),
ot = ref(``),
st = computed(
() => Xe.value && !Y.value && (!nt.value || rt.value),
),
ct = computed(() => ae.value.filter((e) => e.image?.length)),
lt = computed(() =>
ct.value.find((e) =>
e.image.some((e) => e.id === J.value.image_id),
),
),
ut = computed(() =>
lt.value?.image.find((e) => e.id === J.value.image_id),
),
dt = computed(() => [
...(I.value?.bill_type === `bw`
? [
{
key: `bw`,
label: `带宽上限`,
suffix: `Mbps`,
options: I.value.bw ?? [],
},
]
: []),
...(I.value?.bill_type === `flow`
? [
{
key: `flow`,
label: `流量`,
suffix: `GB`,
options: I.value.flow ?? [],
},
]
: []),
{
key: `ip_num`,
label: `IPv4 地址数量`,
suffix: `个`,
options: I.value?.ip ?? [],
},
]);
function ft(e) {
return e.some((e) => e.type === `step` || e.type === `total`);
}
function $(e) {
return {
min: Math.min(...e.map((e) => Number(e.min_value ?? e.value))),
max: Math.max(...e.map((e) => Number(e.max_value ?? e.value))),
step: Number(e[0]?.step) || 1,
};
}
function pt(e, t) {
return e.value_show || e.desc || `${e.value} ${t}`;
}
function mt(e, t) {
((J.value[e] = t === null ? `` : String(t)), N.refresh());
}
let ht = computed(() =>
X.value?.support_optional === 1 &&
X.value.optional_only_for_upgrade !== 1
? [
{
key: `optional_memory`,
label: `选配内存`,
options: X.value.optional_memory ?? [],
max: X.value.max_memory_num,
},
{
key: `optional_disk`,
label: `选配硬盘`,
options: X.value.optional_disk ?? [],
max: X.value.max_disk_num,
},
{
key: `optional_gpu`,
label: `选配显卡`,
options: X.value.optional_gpu ?? [],
max: X.value.max_gpu_num,
},
].filter((e) => e.options.length)
: [],
),
gt = computed(() =>
ht.value.find((e) => e.key === `optional_disk`),
),
_t = computed(() =>
ht.value.filter((e) => e.key !== `optional_disk`),
);
function vt() {
((J.value.data_center_id = Z.value?.data_center_id ?? 0),
N.refresh());
}
function yt(e) {
let t = ct.value.find((t) => t.id === e);
((J.value.image_id = t?.image[0]?.id ?? 0), N.refresh());
}
let bt = computed(() => [
{
label: `区域`,
value: Z.value?.location || `未选择`,
},
{
label: `线路`,
value: Z.value?.name || `未选择`,
},
{
label: `实例`,
value: X.value?.name || `未选择`,
},
{
label: `操作系统`,
value: os_name_t(ut.value?.name) || `未选择`,
},
{
label: `公网 IP`,
value: J.value.ip_num ? `${J.value.ip_num} IPv4` : `未选择`,
},
{
label: I.value?.bill_type === `flow` ? `流量` : `带宽上限`,
value:
I.value?.bill_type === `flow`
? `${J.value.flow || `—`} GB`
: `${J.value.bw || `—`} Mbps`,
},
...(I.value?.defence?.length
? [
{
label: `防护`,
value:
I.value.defence.find(
(e) => Number(e.value) === J.value.peak_defence,
)?.desc || `${J.value.peak_defence} Gbps`,
},
]
: []),
]);
async function xt(e) {
// 如配置了服务条款链接,必须先同意;即时购买发 settled,编辑成功返回购物车。
if (st.value) {
((it.value = e), (at.value = ``), (ot.value = ``));
try {
let t = await (e === `cart` ? N.addToCart() : N.buyNow());
if (e === `cart` && v.edit) {
await navigateTo(`/cart`);
return;
}
e === `cart` ? (ot.value = `已加入购物车`) : ee(`settled`, t);
} catch (e) {
at.value = e instanceof Error ? e.message : `提交失败,请重试`;
} finally {
it.value = null;
}
}
}
return (
onMounted(() => {
(N.init(), tt.load());
}),
(n, r) => {
let a = ConfigLoadingShell,
o = message,
c = button,
d = NuxtLink,
x = select,
S = inputnumber,
ee = slider,
w = ConfigChoiceGrid,
T = textarea,
ae = ProductCustomFields,
z = checkbox,
tt = ConfigCheckout;
return (
openBlock(),
createElementBlock(`div`, B, [
unref(qe)
? (openBlock(),
createBlock(a, {
key: 0,
}))
: !unref(P) || !unref(X)
? (openBlock(),
createElementBlock(`div`, se, [
createVNode(
o,
{
severity: `error`,
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(
toDisplayString(
unref(Ye) || `当前商品暂无可订购型号`,
),
1,
),
]),
_: 1,
},
),
createVNode(c, {
label: `重新加载配置`,
icon: `pi pi-refresh`,
severity: `secondary`,
outlined: ``,
onClick: (r[0] ||= (e) => unref(N).init()),
}),
createVNode(
d,
{
to: `/products/dedicated-server`,
},
{
default: withCtx(() => [
...(r[23] ||= [
createTextVNode(`返回物理服务器列表`, -1),
]),
]),
_: 1,
},
),
]))
: (openBlock(),
createElementBlock(`div`, V, [
createElementVNode(`div`, H, [
createElementVNode(`section`, U, [
(r[38] ||= createElementVNode(
`h2`,
{
class: `section-title`,
},
`基础配置`,
-1,
)),
createElementVNode(`div`, W, [
createElementVNode(
`h3`,
null,
toDisplayString(unref(X).name),
1,
),
createElementVNode(`div`, ce, [
createElementVNode(`div`, null, [
(r[25] ||= createElementVNode(
`i`,
{
class: `pi pi-microchip`,
"aria-hidden": `true`,
},
null,
-1,
)),
createElementVNode(`span`, null, [
(r[24] ||= createTextVNode(`CPU`, -1)),
createElementVNode(
`strong`,
null,
toDisplayString(unref(X).cpu),
1,
),
createElementVNode(
`small`,
null,
toDisplayString(unref(X).cpu_param),
1,
),
]),
]),
createElementVNode(`div`, null, [
(r[27] ||= createElementVNode(
`i`,
{
class: `pi pi-database`,
"aria-hidden": `true`,
},
null,
-1,
)),
createElementVNode(`span`, null, [
(r[26] ||= createTextVNode(`内存`, -1)),
createElementVNode(
`strong`,
null,
toDisplayString(unref(X).memory),
1,
),
]),
]),
createElementVNode(`div`, null, [
(r[29] ||= createElementVNode(
`i`,
{
class: `pi pi-map-marker`,
"aria-hidden": `true`,
},
null,
-1,
)),
createElementVNode(`span`, null, [
(r[28] ||= createTextVNode(`区域`, -1)),
createElementVNode(
`strong`,
null,
toDisplayString(
unref(Z)?.location || `未选择`,
),
1,
),
]),
]),
createElementVNode(`div`, null, [
(r[31] ||= createElementVNode(
`i`,
{
class: `pi pi-share-alt`,
"aria-hidden": `true`,
},
null,
-1,
)),
createElementVNode(`span`, null, [
(r[30] ||= createTextVNode(`线路`, -1)),
createElementVNode(
`strong`,
null,
toDisplayString(
unref(Z)?.name || `未选择`,
),
1,
),
]),
]),
createElementVNode(`div`, null, [
(r[33] ||= createElementVNode(
`i`,
{
class: `pi pi-calendar`,
"aria-hidden": `true`,
},
null,
-1,
)),
createElementVNode(`span`, null, [
(r[32] ||= createTextVNode(
`计费方式`,
-1,
)),
createElementVNode(
`strong`,
null,
toDisplayString(
unref(I)?.bill_type === `flow`
? `流量计费`
: `固定带宽`,
),
1,
),
]),
]),
createElementVNode(`div`, null, [
(r[34] ||= createElementVNode(
`i`,
{
class: `pi pi-sort-alt`,
"aria-hidden": `true`,
},
null,
-1,
)),
createElementVNode(`span`, null, [
createTextVNode(
toDisplayString(
unref(I)?.bill_type === `flow`
? `流量`
: `带宽上限`,
),
1,
),
createElementVNode(
`strong`,
null,
toDisplayString(
unref(I)?.bill_type === `flow`
? `${unref(J).flow || `—`} GB`
: `${unref(J).bw || `—`} Mbps`,
),
1,
),
]),
]),
createElementVNode(`div`, null, [
(r[36] ||= createElementVNode(
`i`,
{
class: `pi pi-shield`,
"aria-hidden": `true`,
},
null,
-1,
)),
createElementVNode(`span`, null, [
(r[35] ||= createTextVNode(`防护`, -1)),
createElementVNode(
`strong`,
null,
toDisplayString(
unref(I)?.defence?.find(
(e) =>
Number(e.value) ===
unref(J).peak_defence,
)?.desc || `按线路配置`,
),
1,
),
]),
]),
]),
(unref(P).model_config?.length || 0) > 1 ||
unref(et).length > 1
? (openBlock(),
createElementBlock(`details`, G, [
(r[37] ||= createElementVNode(
`summary`,
null,
[
createTextVNode(
`更改型号、区域及线路`,
),
createElementVNode(`i`, {
class: `pi pi-chevron-down`,
"aria-hidden": `true`,
}),
],
-1,
)),
createElementVNode(`div`, K, [
(unref(P).model_config?.length || 0) > 1
? (openBlock(),
createElementBlock(`div`, q, [
createElementVNode(
`span`,
{
id: `${unref(M)}-model-label`,
},
`服务器型号`,
8,
le,
),
createVNode(
x,
{
modelValue:
unref(J).model_config_id,
"onUpdate:modelValue":
(r[1] ||= (e) =>
(unref(
J,
).model_config_id = e)),
"aria-labelledby": `${unref(M)}-model-label`,
options:
unref(P).model_config,
"option-label": `name`,
"option-value": `id`,
disabled: unref(Y),
onChange: (r[2] ||= (e) =>
unref(N).refresh()),
},
null,
8,
[
`modelValue`,
`aria-labelledby`,
`options`,
`disabled`,
],
),
]))
: createCommentVNode(``, !0),
unref(et).length > 1
? (openBlock(),
createElementBlock(`div`, ue, [
createElementVNode(
`span`,
{
id: `${unref(M)}-line-label`,
},
`区域及线路`,
8,
de,
),
createVNode(
x,
{
modelValue: unref(J).line_id,
"onUpdate:modelValue":
(r[3] ||= (e) =>
(unref(J).line_id = e)),
"aria-labelledby": `${unref(M)}-line-label`,
options: unref(et).map(
(e) => ({
...e,
label: `${e.location} | ${e.name}`,
}),
),
"option-label": `label`,
"option-value": `id`,
disabled: unref(Y),
onChange: vt,
},
null,
8,
[
`modelValue`,
`aria-labelledby`,
`options`,
`disabled`,
],
),
]))
: createCommentVNode(``, !0),
]),
]))
: createCommentVNode(``, !0),
]),
]),
unref(X).disk || unref(gt)
? (openBlock(),
createElementBlock(`section`, fe, [
(r[39] ||= createElementVNode(
`h2`,
{
class: `section-title`,
},
`存储配置`,
-1,
)),
createElementVNode(`div`, pe, [
unref(X).disk
? (openBlock(),
createBlock(
ConfigDiskCard,
{
key: 0,
label: `标配硬盘`,
title: unref(X).disk,
description: `随服务器型号提供`,
},
null,
8,
[`title`],
))
: createCommentVNode(``, !0),
(openBlock(!0),
createElementBlock(
Fragment,
null,
renderList(
unref(gt)?.options ?? [],
(e) => (
openBlock(),
createBlock(
ConfigDiskCard,
{
key: e.id,
label: `选配硬盘`,
title: String(e.value),
description: e.desc,
disabled: unref(Y),
},
{
default: withCtx(() => [
createElementVNode(`div`, me, [
createElementVNode(
`label`,
{
for: `${unref(M)}-optional_disk-${e.id}`,
},
`数量`,
8,
he,
),
createVNode(
S,
{
modelValue:
unref(J).optional_disk[
String(e.id)
],
"onUpdate:modelValue": [
(t) =>
(unref(
J,
).optional_disk[
String(e.id)
] = t),
(r[4] ||= (e) =>
unref(N).refresh()),
],
"input-id": `${unref(M)}-optional_disk-${e.id}`,
"aria-label": `${e.value} 数量`,
min: 0,
max: unref(gt)?.max,
suffix: ` 块`,
"show-buttons": ``,
"button-layout": `horizontal`,
disabled: unref(Y),
},
null,
8,
[
`modelValue`,
`onUpdate:modelValue`,
`input-id`,
`aria-label`,
`max`,
`disabled`,
],
),
]),
]),
_: 2,
},
1032,
[
`title`,
`description`,
`disabled`,
],
)
),
),
128,
)),
]),
]))
: createCommentVNode(``, !0),
createElementVNode(`section`, ge, [
(r[40] ||= createElementVNode(
`h2`,
{
class: `section-title`,
},
`网络配置`,
-1,
)),
(openBlock(!0),
createElementBlock(
Fragment,
null,
renderList(
unref(dt),
(n) => (
openBlock(),
createElementBlock(
`div`,
{
key: n.key,
class: `form-row`,
},
[
createElementVNode(
`label`,
{
id: `${unref(M)}-${n.key}-label`,
for: ft(n.options)
? `${unref(M)}-${n.key}`
: void 0,
},
toDisplayString(n.label),
9,
_e,
),
ft(n.options)
? (openBlock(),
createElementBlock(
Fragment,
{
key: 0,
},
[
createVNode(
S,
{
"input-id": `${unref(M)}-${n.key}`,
"model-value":
unref(J)[n.key] === ``
? null
: Number(
unref(J)[n.key],
),
min: $(n.options).min,
max: $(n.options).max,
step: $(n.options).step,
suffix: ` ${n.suffix}`,
disabled: unref(Y),
"onUpdate:modelValue": (
e,
) => mt(n.key, e),
},
null,
8,
[
`input-id`,
`model-value`,
`min`,
`max`,
`step`,
`suffix`,
`disabled`,
`onUpdate:modelValue`,
],
),
createVNode(
ee,
{
"model-value": Number(
unref(J)[n.key],
),
"aria-labelledby": `${unref(M)}-${n.key}-label`,
min: $(n.options).min,
max: $(n.options).max,
step: $(n.options).step,
disabled: unref(Y),
class: `network-slider`,
onChange: (e) =>
mt(n.key, Number(e)),
},
null,
8,
[
`model-value`,
`aria-labelledby`,
`min`,
`max`,
`step`,
`disabled`,
`onChange`,
],
),
],
64,
))
: n.options.length
? (openBlock(),
createElementBlock(
`div`,
{
key: 1,
class: `config-choices compact`,
role: `group`,
"aria-labelledby": `${unref(M)}-${n.key}-label`,
},
[
(openBlock(!0),
createElementBlock(
Fragment,
null,
renderList(
n.options,
(t) => (
openBlock(),
createElementBlock(
`button`,
{
key: String(
t.value,
),
type: `button`,
class:
normalizeClass([
`config-choice`,
{
active:
unref(J)[
n.key
] ===
String(
t.value,
),
},
]),
"aria-pressed":
unref(J)[
n.key
] ===
String(t.value),
disabled: unref(Y),
onClick: (e) => {
((unref(J)[
n.key
] = String(
t.value,
)),
unref(
N,
).refresh());
},
},
toDisplayString(
pt(t, n.suffix),
),
11,
ye,
)
),
),
128,
)),
],
8,
ve,
))
: (openBlock(),
createBlock(
o,
{
key: 2,
severity: `warn`,
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(
`当前线路暂未提供` +
toDisplayString(
n.label,
) +
`选项`,
1,
),
]),
_: 2,
},
1024,
)),
],
)
),
),
128,
)),
unref(I)?.defence?.length
? (openBlock(),
createElementBlock(`div`, be, [
createElementVNode(
`span`,
{
id: `${unref(M)}-defence-label`,
},
`防护峰值`,
8,
xe,
),
createElementVNode(
`div`,
{
class: `config-choices compact`,
role: `group`,
"aria-labelledby": `${unref(M)}-defence-label`,
},
[
(openBlock(!0),
createElementBlock(
Fragment,
null,
renderList(
unref(I).defence,
(t) => (
openBlock(),
createElementBlock(
`button`,
{
key: String(t.value),
type: `button`,
class: normalizeClass([
`config-choice`,
{
active:
unref(J)
.peak_defence ===
Number(t.value),
},
]),
"aria-pressed":
unref(J).peak_defence ===
Number(t.value),
disabled: unref(Y),
onClick: (e) => {
((unref(J).peak_defence =
Number(t.value)),
unref(N).refresh());
},
},
toDisplayString(pt(t, `Gbps`)),
11,
Ce,
)
),
),
128,
)),
],
8,
Se,
),
]))
: createCommentVNode(``, !0),
]),
unref(_t).length
? (openBlock(),
createElementBlock(`section`, we, [
(r[41] ||= createElementVNode(
`h2`,
{
class: `section-title`,
},
`增值选配`,
-1,
)),
(openBlock(!0),
createElementBlock(
Fragment,
null,
renderList(
unref(_t),
(n) => (
openBlock(),
createElementBlock(
`div`,
{
key: n.key,
class: `optional-group`,
},
[
createElementVNode(
`h3`,
null,
toDisplayString(n.label),
1,
),
(openBlock(!0),
createElementBlock(
Fragment,
null,
renderList(
n.options,
(t) => (
openBlock(),
createElementBlock(
`div`,
{
key: t.id,
class: `optional-row`,
},
[
createElementVNode(
`label`,
{
for: `${unref(M)}-${n.key}-${t.id}`,
},
toDisplayString(
t.value,
),
9,
Te,
),
createVNode(
S,
{
modelValue:
unref(J)[n.key][
String(t.id)
],
"onUpdate:modelValue":
[
(e) =>
(unref(J)[
n.key
][
String(t.id)
] = e),
(r[5] ||= (e) =>
unref(
N,
).refresh()),
],
"input-id": `${unref(M)}-${n.key}-${t.id}`,
min: 0,
max: n.max,
"show-buttons": ``,
"button-layout": `horizontal`,
disabled: unref(Y),
},
null,
8,
[
`modelValue`,
`onUpdate:modelValue`,
`input-id`,
`max`,
`disabled`,
],
),
],
)
),
),
128,
)),
],
)
),
),
128,
)),
]))
: createCommentVNode(``, !0),
createElementVNode(`section`, Ee, [
(r[42] ||= createElementVNode(
`h2`,
{
class: `section-title`,
},
`操作系统`,
-1,
)),
createVNode(
w,
{
label: `操作系统`,
images: ``,
"model-value": unref(lt)?.id,
options: unref(ct).map((e) => ({
label: unref(os_name_t)(e.name),
value: e.id,
iconUrl: e.icon_url,
icon: e.icon,
})),
disabled: unref(Y),
"onUpdate:modelValue": yt,
},
null,
8,
[`model-value`, `options`, `disabled`],
),
createElementVNode(`div`, De, [
createElementVNode(
`span`,
{
id: `${unref(M)}-image-label`,
},
`镜像版本`,
8,
Oe,
),
createVNode(
x,
{
modelValue: unref(J).image_id,
"onUpdate:modelValue": (r[6] ||= (e) =>
(unref(J).image_id = e)),
"aria-labelledby": `${unref(M)}-image-label`,
options: unref(lt)?.image ?? [],
"option-label": (e) =>
unref(os_name_t)(e.name),
"option-value": `id`,
placeholder: `请选择镜像版本`,
disabled: unref(Y),
onChange: (r[7] ||= (e) =>
unref(N).refresh()),
},
null,
8,
[
`modelValue`,
`aria-labelledby`,
`options`,
`option-label`,
`disabled`,
],
),
unref(ut)?.charge === 1
? (openBlock(),
createElementBlock(
`small`,
ke,
`此镜像为付费镜像,费用以当前配置报价为准。`,
))
: createCommentVNode(``, !0),
]),
]),
createElementVNode(`section`, Ae, [
(r[43] ||= createElementVNode(
`h2`,
{
class: `section-title`,
},
`其他设置`,
-1,
)),
createElementVNode(`div`, je, [
createElementVNode(
`label`,
{
for: `${unref(M)}-notes`,
},
`备注`,
8,
Me,
),
createVNode(
T,
{
id: `${unref(M)}-notes`,
modelValue: unref(J).notes,
"onUpdate:modelValue": (r[8] ||= (e) =>
(unref(J).notes = e)),
rows: `3`,
placeholder: `填写实例用途或备注(选填)`,
disabled: unref(Y),
onChange: (r[9] ||= (e) =>
unref(N).calcPrice()),
},
null,
8,
[`id`, `modelValue`, `disabled`],
),
]),
]),
createVNode(
ae,
{
modelValue: unref(Ue),
"onUpdate:modelValue": (r[10] ||= (e) =>
isRef(Ue) ? (Ue.value = e) : null),
fields: unref(We),
disabled: unref(Y),
},
null,
8,
[`modelValue`, `fields`, `disabled`],
),
]),
createVNode(
tt,
{
"product-id": v.productId,
quantity: unref(Ge),
"edit-position": v.edit?.position,
editing: !!v.edit,
summary: unref(bt),
price: unref(Ke),
"quote-ready": unref(Xe),
"price-loading": unref(Je),
"can-submit": unref(st),
"active-action": unref(it),
disabled: unref(Y),
"promo-code": unref(Ze),
"onUpdate:promoCode": (r[18] ||= (e) =>
isRef(Ze) ? (Ze.value = e) : null),
"promo-discount": unref(Qe),
"level-discount": unref($e),
error: unref(Ye),
"action-error": unref(at),
"cart-tip": unref(ot),
onCart: (r[19] ||= (e) => xt(`cart`)),
onBuy: (r[20] ||= (e) => xt(`buy`)),
onRecalc: (r[21] ||= (e) => unref(N).calcPrice()),
onRetry: (r[22] ||= (e) => unref(N).refresh()),
},
{
agreement: withCtx(() => [
unref(nt)
? (openBlock(),
createElementBlock(`div`, Be, [
createVNode(
z,
{
modelValue: unref(rt),
"onUpdate:modelValue": (r[17] ||= (
e,
) =>
isRef(rt) ? (rt.value = e) : null),
"input-id": `${unref(M)}-terms`,
binary: ``,
disabled: unref(Y),
},
null,
8,
[`modelValue`, `input-id`, `disabled`],
),
createElementVNode(
`label`,
{
for: `${unref(M)}-terms`,
},
[
(r[44] ||= createTextVNode(
`我已阅读并同意 `,
-1,
)),
createElementVNode(
`a`,
{
href: unref(nt),
target: `_blank`,
rel: `noopener noreferrer`,
},
`《服务协议》`,
8,
He,
),
],
8,
Ve,
),
]))
: createCommentVNode(``, !0),
]),
default: withCtx(() => [
createElementVNode(`div`, Ne, [
createElementVNode(
`span`,
{
id: `${unref(M)}-duration-label`,
},
`购买时长`,
8,
Pe,
),
createVNode(
x,
{
modelValue: unref(J).duration_id,
"onUpdate:modelValue": (r[11] ||= (e) =>
(unref(J).duration_id = e)),
"aria-labelledby": `${unref(M)}-duration-label`,
options: unref(oe),
"option-label": `name`,
"option-value": `id`,
placeholder: `请选择购买时长`,
disabled: unref(Y) || unref(Je),
onChange: (r[12] ||= (e) =>
unref(N).calcPrice()),
},
null,
8,
[
`modelValue`,
`aria-labelledby`,
`options`,
`disabled`,
],
),
]),
createElementVNode(`div`, Fe, [
createElementVNode(
`label`,
{
for: `${unref(M)}-qty`,
},
`购买数量`,
8,
Ie,
),
createVNode(
S,
{
modelValue: unref(Ge),
"onUpdate:modelValue": [
(r[13] ||= (e) =>
isRef(Ge) ? (Ge.value = e) : null),
(r[14] ||= (e) => unref(N).calcPrice()),
],
"input-id": `${unref(M)}-qty`,
min: 1,
max:
unref(Q) === null
? 99
: Math.max(1, unref(Q)),
"show-buttons": ``,
"button-layout": `horizontal`,
disabled: unref(Y),
},
null,
8,
[
`modelValue`,
`input-id`,
`max`,
`disabled`,
],
),
unref(Q) === null
? createCommentVNode(``, !0)
: (openBlock(),
createElementBlock(
`small`,
Le,
toDisplayString(
unref(Q)
? `当前库存 ${unref(Q)} 台`
: `库存不足`,
),
1,
)),
]),
createElementVNode(`div`, Re, [
createVNode(
z,
{
modelValue: unref(J).auto_renew,
"onUpdate:modelValue": (r[15] ||= (e) =>
(unref(J).auto_renew = e)),
"input-id": `${unref(M)}-auto-renew`,
binary: !0,
"true-value": 1,
"false-value": 0,
disabled: unref(Y),
onChange: (r[16] ||= (e) =>
unref(N).calcPrice()),
},
null,
8,
[`modelValue`, `input-id`, `disabled`],
),
createElementVNode(
`label`,
{
for: `${unref(M)}-auto-renew`,
},
`到期自动续费`,
8,
ze,
),
]),
]),
_: 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`,
],
),
])),
])
);
}
);
},
}),
[[`__scopeId`, `data-v-b5ff32bb`]],
),
{
__name: `MfDcimConfig`,
},
);
export {};
export default J;
</script>