Files

620 lines
24 KiB
Vue

<script>
// DCIM 资源升级表单:基于当前线路选择带宽、流量、IP、防御及可选硬件数量。
import "~/assets/styles/ConfigBandwidth.CWSH1WJZ.css";
import "~/assets/styles/DcimUpgrade.DaLApYFa.css";
import { toDisplayString } from "vue";
import { renderList } from "vue";
import { onMounted } 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 { reactive } 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 { 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 ConfigBandwidth from "~/components/config/ConfigBandwidth.vue";
var T = {
key: 0,
class: `dcim-upgrade`,
},
E = {
key: 1,
},
te = {
key: 2,
},
D = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `DcimUpgrade`,
props: {
hostId: {},
productId: {},
module: {},
current: {},
upgradeAllowed: {
type: Boolean,
},
},
emits: [`pay`],
setup(h, { expose: b, emit: D }) {
let O = h,
k = D,
A = useApi(),
j = ref(null),
M = computed(() => O.current.model_config ?? {}),
N = [`memory`, `disk`, `gpu`],
P = {
memory: `内存`,
disk: `硬盘`,
gpu: `显卡`,
},
F = reactive({
bw: 0,
flow: 0,
ip_num: 0,
peak_defence: 0,
optional_memory: {},
optional_disk: {},
optional_gpu: {},
}),
I = ref(!1),
L = ref(!1),
R = ref(!1),
z = ref(``),
B = ref(``),
V = ref(``),
H = 0,
U = 0,
W = !1,
G = ``,
K = ``,
q = computed(() => JSON.stringify([O.hostId, O.module, F])),
J = computed(() => q.value !== K),
ne = (e = []) =>
e
.filter(
(e) => e.value !== `` && Number.isFinite(Number(e.value)),
)
.map((e) => ({
value: Number(e.value),
label: String(e.value_show || e.desc || e.value),
})),
re = (e = []) =>
e.some((e) => e.min_value !== void 0 && e.max_value !== void 0),
Y = computed(() =>
[
...(j.value?.bill_type === `flow`
? [
{
key: `flow`,
label: `流量配额`,
options: j.value.flow ?? [],
},
]
: []),
{
key: `ip_num`,
label: `IPv4 数量`,
options: j.value?.ip ?? [],
},
{
key: `peak_defence`,
label: `防御峰值`,
options: j.value?.defence ?? [],
},
].filter((e) => e.options.length),
);
// 档位既可能是离散值,也可能是区间;区间需要同时满足上下限和步长。
function ie(e, t) {
return (
Number.isFinite(e) &&
t.some((t) => {
if (
t.min_value === void 0 ||
t.max_value === void 0 ||
t.type === `radio`
)
return Number(t.value) === e;
let n = Number(t.step ?? 1);
return (
n > 0 &&
e >= Number(t.min_value) &&
e <= Number(t.max_value) &&
Math.abs(
(e - Number(t.min_value)) / n -
Math.round((e - Number(t.min_value)) / n),
) < 1e-7
);
})
);
}
let X = (e) => M.value[`optional_${e}`] ?? [];
function Z() {
(H++, (B.value = ``), (V.value = ``), (G = ``), (L.value = !1));
}
// 从当前实例恢复初值并保存基准快照,只有与基准不同的配置才需要询价。
function ae() {
for (let e of [`bw`, `flow`, `ip_num`, `peak_defence`])
F[e] = Number(O.current[e] ?? 0);
for (let e of N) {
let t = O.current[`optional_${e}`];
F[`optional_${e}`] =
t && typeof t == `object` && !Array.isArray(t)
? Object.fromEntries(
Object.entries(t).map(([e, t]) => [e, Number(t)]),
)
: {};
}
((K = q.value), Z());
}
async function Q() {
if (O.upgradeAllowed === !1 || W) return;
let e = ++U;
(ae(), (I.value = !0), (z.value = ``), (j.value = null));
try {
let t = Number(O.current.line?.id);
if (!Number.isSafeInteger(t) || t <= 0)
throw Error(`实例线路信息无效,请刷新后重试`);
let n = await A.get(
`/product/${O.productId}/${O.module}/line/${t}`,
);
!W && e === U && (j.value = n);
} catch (t) {
!W &&
e === U &&
(z.value = t instanceof Error ? t.message : `升级配置加载失败`);
} finally {
e === U && (I.value = !1);
}
}
// 硬件数量只允许已有/可选项目,新增数量不得超剩余槽位;网络变更需匹配线路档位。
function oe() {
for (let e of N) {
let t = F[`optional_${e}`],
n = O.current[`optional_${e}`] ?? {},
r = new Set([
...X(e).map((e) => String(e.id)),
...Object.keys(n),
]);
if (
Object.entries(t).some(
([e, t]) => !r.has(e) || !Number.isSafeInteger(t) || t < 0,
)
)
throw Error(`${P[e]}数量无效`);
let i =
Object.values(t).reduce((e, t) => e + t, 0) -
Object.values(n).reduce((e, t) => e + Number(t), 0),
a = M.value[`max_${e}_num`];
if (a !== void 0 && i > Number(a))
throw Error(`${P[e]}数量超过剩余槽位`);
}
if (!j.value) throw Error(`请先加载有效的升级配置`);
let e = [
...Y.value,
...(j.value.bill_type === `bw`
? [
{
key: `bw`,
label: `带宽`,
options: j.value.bw ?? [],
},
]
: []),
];
for (let t of e)
if (
F[t.key] !== Number(O.current[t.key] ?? 0) &&
!ie(F[t.key], t.options)
)
throw Error(`请选择有效的${t.label}档位`);
}
// 询价接口使用扁平 optional_*[id] 参数,返回价格仅对当前配置快照有效。
async function $() {
if (O.upgradeAllowed === !1 || R.value || W || !J.value) return;
((z.value = ``), Z());
try {
oe();
} catch (e) {
z.value = e.message;
return;
}
let e = ++H,
t = q.value,
n = JSON.parse(JSON.stringify(F)),
r = {
bw: n.bw,
flow: n.flow,
ip_num: n.ip_num,
peak_defence: n.peak_defence,
};
for (let e of N)
for (let [t, i] of Object.entries(n[`optional_${e}`]))
r[`optional_${e}[${t}]`] = i;
L.value = !0;
try {
let n = await A.get(`/${O.module}/${O.hostId}/common_config`, r);
if (W || e !== H || t !== q.value) return;
if (
n.price === null ||
n.price === void 0 ||
String(n.price).trim() === `` ||
!Number.isFinite(Number(n.price))
)
throw Error(`升级报价无效,请重试`);
((B.value = String(n.price)),
(V.value = n.description ?? ``),
(G = t));
} catch (t) {
!W &&
e === H &&
(z.value = t instanceof Error ? t.message : `升级询价失败`);
} finally {
e === H && (L.value = !1);
}
}
// 下单使用完整嵌套配置,并在报价、配置快照一致后把有效订单交给支付入口。
async function se() {
if (
O.upgradeAllowed === !1 ||
R.value ||
L.value ||
!J.value ||
!B.value ||
G !== q.value ||
W
)
return;
let e = q.value,
t = B.value,
n = JSON.parse(JSON.stringify(F));
((R.value = !0), (z.value = ``));
try {
let r = await A.post(
`/${O.module}/${O.hostId}/common_config/order`,
n,
);
if (W || e !== q.value) return;
if (!/^[1-9]\d*$/.test(String(r.id)))
throw Error(`升级订单无效,请重试`);
(Z(),
k(`pay`, {
order_id: r.id,
amount: t,
}));
} catch (t) {
!W &&
e === q.value &&
(z.value = t instanceof Error ? t.message : `升级订单创建失败`);
} finally {
W || (R.value = !1);
}
}
return (
watch(F, Z, {
deep: !0,
flush: `sync`,
}),
watch(
[
() => O.hostId,
() => O.module,
() => O.current,
() => O.upgradeAllowed,
],
() => {
(U++, Z(), Q());
},
{
flush: `sync`,
},
),
onMounted(Q),
onBeforeUnmount(() => {
((W = !0), H++, U++);
}),
b({
busy: R,
}),
(n, r) => {
let i = message,
o = button,
l = ConfigBandwidth,
u = inputnumber,
v = select;
return h.upgradeAllowed === !1
? createCommentVNode(``, !0)
: (openBlock(),
createElementBlock(`div`, T, [
unref(z)
? (openBlock(),
createBlock(
i,
{
key: 0,
severity: `error`,
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(toDisplayString(unref(z)), 1),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
unref(j)
? createCommentVNode(``, !0)
: (openBlock(),
createBlock(
o,
{
key: 1,
label: `加载升级配置`,
text: ``,
loading: unref(I),
onClick: Q,
},
null,
8,
[`loading`],
)),
unref(j)
? (openBlock(),
createElementBlock(
Fragment,
{
key: 2,
},
[
unref(j).bill_type === `bw` && unref(j).bw?.length
? (openBlock(),
createBlock(
l,
{
key: 0,
modelValue: unref(F).bw,
"onUpdate:modelValue": (r[0] ||= (e) =>
(unref(F).bw = e)),
options: unref(j).bw,
disabled: unref(R),
onChange: $,
},
null,
8,
[`modelValue`, `options`, `disabled`],
))
: createCommentVNode(``, !0),
(openBlock(!0),
createElementBlock(
Fragment,
null,
renderList(
unref(Y),
(t) => (
openBlock(),
createElementBlock(
`label`,
{
key: t.key,
},
[
createTextVNode(
toDisplayString(t.label),
1,
),
re(t.options)
? (openBlock(),
createBlock(
u,
{
key: 0,
modelValue: unref(F)[t.key],
"onUpdate:modelValue": (e) =>
(unref(F)[t.key] = e),
min: 0,
disabled: unref(R),
"use-grouping": !1,
},
null,
8,
[
`modelValue`,
`onUpdate:modelValue`,
`disabled`,
],
))
: (openBlock(),
createBlock(
v,
{
key: 1,
modelValue: unref(F)[t.key],
"onUpdate:modelValue": (e) =>
(unref(F)[t.key] = e),
options: ne(t.options),
"option-label": `label`,
"option-value": `value`,
disabled: unref(R),
},
null,
8,
[
`modelValue`,
`onUpdate:modelValue`,
`options`,
`disabled`,
],
)),
],
)
),
),
128,
)),
(openBlock(!0),
createElementBlock(
Fragment,
null,
renderList(
N.filter((e) => X(e).length),
(n) => (
openBlock(),
createElementBlock(
`fieldset`,
{
key: n,
},
[
createElementVNode(
`legend`,
null,
toDisplayString(P[n]) + `配置`,
1,
),
(openBlock(!0),
createElementBlock(
Fragment,
null,
renderList(
X(n),
(t) => (
openBlock(),
createElementBlock(
`label`,
{
key: t.id,
},
[
createTextVNode(
toDisplayString(t.value),
1,
),
createVNode(
u,
{
modelValue:
unref(F)[`optional_${n}`][
String(t.id)
],
"onUpdate:modelValue": (
e,
) =>
(unref(F)[
`optional_${n}`
][String(t.id)] = e),
min: 0,
max:
Number(
unref(M)[
`max_${n}_num`
] ?? 99,
) +
Number(
h.current[
`optional_${n}`
]?.[String(t.id)] ?? 0,
),
disabled: unref(R),
"use-grouping": !1,
},
null,
8,
[
`modelValue`,
`onUpdate:modelValue`,
`max`,
`disabled`,
],
),
],
)
),
),
128,
)),
],
)
),
),
128,
)),
createVNode(
o,
{
label: `计算变更费用`,
outlined: ``,
loading: unref(L),
disabled: unref(R) || !unref(J),
onClick: $,
},
null,
8,
[`loading`, `disabled`],
),
unref(B) === ``
? createCommentVNode(``, !0)
: (openBlock(),
createElementBlock(
`p`,
E,
`变更费用:¥` + toDisplayString(unref(B)),
1,
)),
unref(V)
? (openBlock(),
createElementBlock(
`p`,
te,
toDisplayString(unref(V)),
1,
))
: createCommentVNode(``, !0),
createVNode(
o,
{
label: `确认生成升级订单`,
loading: unref(R),
disabled:
unref(B) === `` || unref(L) || !unref(J),
onClick: se,
},
null,
8,
[`loading`, `disabled`],
),
],
64,
))
: createCommentVNode(``, !0),
]));
}
);
},
}),
[[`__scopeId`, `data-v-790898bc`]],
),
{
__name: `DcimUpgrade`,
},
);
export {};
export default D;
</script>