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

3657 lines
155 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/PaymentDialog.BNFKQF1U.css";
import "~/assets/styles/OsIcon.CAi4Iz2S.css";
import "~/assets/styles/HostList.B3U15sJm.css";
import { nextTick } from "vue";
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 { onScopeDispose } from "vue";
import { createBlock } from "vue";
import { ref } from "vue";
import { withCtx } from "vue";
import { createCommentVNode } from "vue";
import { computed } from "vue";
import { effectScope } 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 { normalizeStyle } from "vue";
import { withModifiers } from "vue";
import { navigateTo } from "#app";
import { NuxtLink } from "#components";
import { sanitizeMessage } from "~/lib/auth.js";
import { useApi } from "~/lib/auth.js";
import { useAuth } from "~/lib/auth.js";
import dialog from "primevue/dialog";
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 inputtext from "primevue/inputtext";
import { n as product_name_n } from "~/lib/product-name.js";
import { c as dict_c } from "~/lib/dict.js";
import { l as dict_l } from "~/lib/dict.js";
import { r as dict_r } from "~/lib/dict.js";
import datatable from "primevue/datatable";
import paginator from "primevue/paginator";
import select from "primevue/select";
import column from "primevue/column";
import ListSegments from "~/components/ListSegments.vue";
import ListEmpty from "~/components/ListEmpty.vue";
import { n as modules_n } from "~/lib/modules.js";
import OsIcon from "~/components/OsIcon.vue";
import OperationNotice from "~/components/OperationNotice.vue";
import OperatePasswordGate from "~/components/OperatePasswordGate.vue";
import PaymentDialog from "~/components/PaymentDialog.vue";
import { t as useListPage_t } from "~/lib/useListPage.js";
import { r as instance_status_r } from "~/lib/instance-status.js";
import { t as instance_status_t } from "~/lib/instance-status.js";
import password from "primevue/password";
import textarea from "primevue/textarea";
import menu from "primevue/menu";
import tag from "primevue/tag";
import skeleton from "primevue/skeleton";
import { t as server_page_t } from "~/lib/server-page.js";
import { a as instance_data_a } from "~/lib/instance-data.js";
import { d as instance_data_d } from "~/lib/instance-data.js";
import { n as instance_data_n } from "~/lib/instance-data.js";
import { r as instance_data_r } from "~/lib/instance-data.js";
import { t as os_name_t } from "~/lib/os-name.js";
import { t as configuration_display_t } from "~/lib/configuration-display.js";
import { n as renewal_quote_n } from "~/lib/renewal-quote.js";
import { r as renewal_quote_r } from "~/lib/renewal-quote.js";
import { t as renewal_quote_t } from "~/lib/renewal-quote.js";
var T = new WeakMap();
function We(e, t) {
let n = T.get(e);
if (!n) {
((n = {
states: new Map(),
version: 0,
}),
T.set(e, n));
let t = n;
effectScope(!0).run(() =>
watch(
() => e.token,
() => {
(t.states.clear(), t.version++);
},
{
flush: `sync`,
},
),
);
}
let r = n,
i = r.version;
return {
read: () => (e.token && r.version === i ? r.states.get(t) : void 0),
save(n) {
e.token &&
r.version === i &&
r.states.set(t, {
tab: n.tab,
keywords: n.keywords,
appliedKeywords: n.appliedKeywords,
sortField: n.sortField,
sortOrder: n.sortOrder,
page: n.page,
limit: n.limit,
scrollY: n.scrollY,
});
},
};
}
function Ge(e, t) {
let n = ref({}),
r = 0,
i = !1,
a = 0,
o = 0,
l = new Map(),
d = [];
function f(e) {
return (
(typeof e.power_status_module == `string` &&
e.power_status_module.trim()) ||
void 0
);
}
function p() {
(r++, (d = []), l.clear(), (n.value = {}));
}
function m(e) {
return (
!i &&
e.version === r &&
e.identity === t.identity() &&
e.request === l.get(e.id) &&
t.hosts.value.some((t) => t.id === e.id && t.status === `Active`)
);
}
async function h(t) {
try {
let r = t.module;
if (!r) {
let n = await e.get(`/host/${t.id}/view`, void 0, !1, {
timeoutMs: 12e3,
});
if (!m(t)) return;
r = n && typeof n == `object` ? n.module : null;
}
let i = typeof r == `string` ? await instance_status_r(e, r, t.id) : ``;
m(t) &&
(n.value[t.id] = {
value: i,
loading: !1,
});
} catch {
m(t) &&
(n.value[t.id] = {
value: ``,
loading: !1,
});
} finally {
(a--, g());
}
}
function g() {
for (; !i && a < 3 && d.length;) {
let e = d.shift();
m(e) && (a++, h(e));
}
}
function ee() {
if ((p(), i || t.loading.value || t.error.value)) return;
let e = t.identity(),
a = new Set();
for (let i of t.hosts.value) {
if (
i.status !== `Active` ||
!Number.isSafeInteger(i.id) ||
i.id <= 0 ||
a.has(i.id)
)
continue;
a.add(i.id);
let t =
typeof i.power_status == `string`
? i.power_status.trim().toLowerCase()
: ``;
n.value[i.id] = {
value: [
`on`,
`off`,
`suspend`,
`suspended`,
`paused`,
`pending`,
`operating`,
`fault`,
].includes(t)
? t
: ``,
loading: !0,
};
let s = ++o;
(l.set(i.id, s),
d.push({
id: i.id,
version: r,
identity: e,
module: f(i),
request: s,
}));
}
g();
}
function _(e) {
if (i || t.loading.value || t.error.value) return;
let a = new Set(e);
d = d.filter((e) => !a.has(e.id));
let s = [];
for (let e of t.hosts.value) {
if (
!a.has(e.id) ||
e.status !== `Active` ||
!Number.isSafeInteger(e.id) ||
e.id <= 0
)
continue;
a.delete(e.id);
let i = ++o;
(l.set(e.id, i),
(n.value[e.id] = {
value: `operating`,
loading: !0,
}),
s.push({
id: e.id,
version: r,
identity: t.identity(),
module: f(e),
request: i,
}));
}
(d.unshift(...s), g());
}
function v(e) {
let t = n.value[e.id];
return instance_status_t(t?.value, e.status, t?.loading);
}
return (
watch([t.hosts, t.loading, t.error], ee, {
flush: `sync`,
}),
watch(t.identity, p, {
flush: `sync`,
}),
onScopeDispose(() => {
((i = !0), p());
}),
{
statusOf: v,
refresh: ee,
refreshAfterPower: _,
reset: p,
}
);
}
var E = [`on`, `off`, `reboot`, `hard_off`, `hard_reboot`],
D = [`on`, `off`, `reboot`],
O = {};
for (let e of [
`mf_cloud`,
`remf_cloud`,
`remf_finance`,
`rewhmcs_cloud`,
`idcsmart_common`,
])
O[e] = {
path: `/${e}/batch_operate`,
actions: E,
};
for (let e of [
`mf_dcim`,
`remf_dcim`,
`remf_finance_dcim`,
`remf_finance_common`,
`rewhmcs_dcim`,
])
O[e] = {
path: `/${e}/batch_operate`,
actions: D,
};
function Ke(e) {
return O[e] || O[`re${e}`];
}
function qe(e) {
return typeof e == `string` ? O[e] : void 0;
}
function Je(e, t) {
let n = Array.isArray(e) ? e : [];
return t.map((e) => {
let t = n.filter((t) => t && typeof t == `object` && Number(t.id) === e),
r = t.length === 1 ? t[0] : void 0,
i = r && Number(r.status) === 200;
return {
ids: [e],
success: !!i,
message:
r && typeof r.msg == `string` && r.msg.trim()
? r.msg
: i
? `指令已下发`
: `未收到明确的操作结果,请刷新实例状态后重试`,
};
});
}
var Ye = {
class: `list-page host-list-page`,
},
Xe = {
class: `list-head`,
},
Ze = {
class: `list-head-actions`,
},
Qe = {
class: `list-toolbar`,
},
$e = {
class: `list-toolbar-right`,
},
et = [`aria-label`],
tt = [`aria-busy`],
nt = {
key: 0,
class: `host-loading-status`,
role: `status`,
},
rt = {
key: 1,
class: `col-mono`,
},
it = {
key: 2,
class: `muted`,
},
at = {
key: 1,
},
ot = {
key: 0,
class: `host-row-placeholder`,
},
st = {
key: 1,
class: `host-product`,
},
ct = [`aria-label`, `title`, `disabled`, `onClick`],
lt = {
class: `host-notes-text`,
},
ut = {
key: 1,
},
dt = {
key: 1,
},
ft = {
key: 1,
},
pt = {
key: 1,
},
mt = {
key: 0,
class: `host-row-placeholder`,
},
ht = [`aria-busy`],
gt = {
key: 0,
class: `traffic-unlimited`,
},
_t = {
class: `traffic-unlimited-copy`,
},
vt = [`title`],
yt = [`aria-valuenow`, `aria-valuetext`, `title`],
bt = [`title`],
xt = [`title`],
St = {
key: 3,
class: `traffic-note`,
},
Ct = {
key: 4,
class: `traffic-note`,
},
wt = {
key: 2,
class: `muted`,
role: `status`,
},
Tt = {
key: 3,
class: `traffic-error`,
},
Et = [`title`],
Dt = {
key: 1,
},
Ot = {
key: 1,
},
kt = {
key: 2,
class: `muted`,
},
At = [`aria-label`, `title`],
jt = [`aria-label`, `title`, `disabled`, `onClick`],
Mt = {
class: `host-notes-text`,
},
Nt = {
key: 0,
class: `table-scroll-hint`,
},
Pt = [`inert`],
Ft = {
class: `list-bulk`,
},
It = {
key: 0,
class: `bulk-count`,
},
Lt = {
class: `host-notes-form`,
},
Rt = {
class: `host-notes-context`,
},
zt = {
class: `host-notes-form`,
},
Bt = {
class: `host-notes-context`,
},
Vt = {
class: `batch-dlg`,
},
Ht = {
class: `confirm-text`,
},
Ut = {
key: 0,
class: `bulk-hint`,
},
Wt = {
class: `form-row`,
},
Gt = {
key: 0,
class: `renew-dlg`,
},
Kt = {
key: 1,
class: `renew-dlg`,
},
qt = {
class: `renew-hint`,
},
Jt = {
class: `renew-prod`,
},
Yt = {
class: `renew-name`,
},
Xt = {
class: `renew-host`,
},
Zt = {
class: `nowrap`,
},
Qt = {
key: 1,
},
$t = {
key: 0,
class: `renew-price`,
},
en = {
key: 1,
},
tn = {
class: `renew-total`,
},
nn = {
class: `form-row`,
},
rn = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `HostList`,
props: {
modules: {},
menuId: {},
title: {},
description: {},
tabs: {},
tabParams: {},
},
setup(c) {
let m = c,
b = useApi(),
w = useAuth(),
De = m.menuId ? `menu:${m.menuId}` : m.modules.join(`,`),
Oe = We(w, De),
T = Oe.read(),
E = server_page_t(b, m.modules, m.menuId),
D = ref(null),
O = 0;
async function rn(e) {
let t = ++O,
n = w.token,
r = await E(e);
return (
t === O &&
n === w.token &&
(D.value = {
select_field: Array.isArray(r.select_field)
? r.select_field
: void 0,
self_defined_field: Array.isArray(r.self_defined_field)
? r.self_defined_field
: [],
}),
r
);
}
function k(e) {
return (
!m.menuId ||
!Array.isArray(D.value?.select_field) ||
D.value.select_field.includes(e)
);
}
function an(e) {
return (
[e.country, e.city, e.area].filter(Boolean).join(` · `) ||
e.data_center ||
`—`
);
}
function on(e, t) {
let n = e.self_defined_field?.[t.id];
return n == null || n === ``
? `—`
: t.field_type === `password`
? `••••••`
: typeof n == `string` || typeof n == `number`
? String(n)
: `—`;
}
let sn = [
{
label: `全部`,
value: ``,
},
{
label: `使用中`,
value: `using`,
},
{
label: `即将到期`,
value: `expiring`,
},
{
label: `已逾期`,
value: `overdue`,
},
{
label: `已删除`,
value: `deleted`,
},
{
label: `未支付`,
value: `unpaid`,
},
{
label: `已暂停`,
value: `suspended`,
},
],
cn = {
using: {
tab: `using`,
},
expiring: {
tab: `expiring`,
},
overdue: {
tab: `overdue`,
},
deleted: {
tab: `deleted`,
},
unpaid: {
status: `Unpaid`,
},
suspended: {
status: `Suspended`,
},
},
ln = computed(() => m.tabs ?? sn),
un = computed(() => m.tabParams ?? cn),
dn = computed(
() =>
m.modules.includes(`idcsmart_common`) &&
!m.modules.includes(`mf_cloud`),
),
A = ref(T?.tab ?? ``),
j = ref(T?.keywords ?? ``),
fn = ref(T?.appliedKeywords ?? ``),
M = ref(T?.sortField === `status` ? `id` : (T?.sortField ?? `id`)),
N = ref(T?.sortOrder ?? -1),
{
list: pn,
total: mn,
loading: P,
error: F,
hasResult: hn,
page: gn,
limit: I,
load: _n,
onPage: vn,
reload: yn,
} = useListPage_t(`/host`, {
limit: 20,
retainOnRefreshError: !0,
rowKey: (e) => e.id,
identity: () => w.token,
snapshotKey: De,
loader: rn,
params: () => ({
module: m.modules.join(`,`),
keywords: fn.value,
orderby: M.value,
sort: N.value === 1 ? `asc` : `desc`,
...(un.value[A.value] ?? {}),
}),
});
((gn.value = T?.page ?? 1), (I.value = T?.limit ?? 20));
let L = computed(() => !hn.value && !F.value),
bn = computed(() =>
Array.from(
{
length: I.value,
},
(e, t) => ({
id: -t - 1,
__skeleton: !0,
}),
),
),
xn = computed(() => (L.value ? bn.value : pn.value)),
Sn = computed(() => P.value || !!F.value || L.value),
Cn = Ge(b, {
hosts: pn,
loading: P,
error: F,
identity: () => w.token,
}),
wn = Cn.statusOf,
Tn = T?.scrollY ?? null;
function En() {
Oe.save({
tab: A.value,
keywords: j.value,
appliedKeywords: fn.value,
sortField: M.value,
sortOrder: N.value,
page: gn.value,
limit: I.value,
scrollY: window.scrollY,
});
}
(onBeforeUnmount(() => {
(O++, En(), (Tn = null));
}),
onMounted(async () => {
(await nextTick(),
requestAnimationFrame(() =>
requestAnimationFrame(() => {
(Tn !== null &&
window.scrollTo({
top: Tn,
behavior: `instant`,
}),
(Tn = null));
}),
));
}),
watch(
() => w.token,
(e) => {
(O++,
(D.value = null),
(Oe = We(w, De)),
(Tn = null),
(A.value = ``),
(j.value = ``),
(fn.value = ``),
(M.value = `id`),
(N.value = -1),
(gn.value = 1),
(I.value = 20),
Cn.reset(),
cr(),
Y++,
(J.value = null),
(Z.value = []),
(Yn.value = ``),
(U.value = null),
(Wn.value = ``),
(G.value = ``),
(er.value = null),
(nr.value = ``),
(rr.value = ``),
R++,
Ln++,
(Fn.value = {}),
(z.value = {}),
In.clear(),
B.clear(),
E.invalidate(!0),
e && _n());
},
{
flush: `sync`,
},
));
function Dn() {
return (
Cn.reset(),
E.invalidate(!0),
R++,
B.clear(),
In.clear(),
_n()
);
}
function On() {
return (E.invalidate(), yn());
}
function kn() {
((fn.value = j.value.trim()), cr(), On());
}
function An() {
(cr(), On());
}
function jn() {
((A.value = ``),
(j.value = ``),
(fn.value = ``),
(M.value = `id`),
(N.value = -1),
cr(),
On());
}
function Mn(e) {
((M.value =
typeof e.sortField == `string` && e.sortField
? e.sortField
: `id`),
(N.value = e.sortOrder === 1 ? 1 : -1),
cr(),
On());
}
let Nn = computed(
() => !!A.value || !!fn.value || M.value !== `id` || N.value !== -1,
);
function Pn(e) {
return e.dedicate_ip || e.assign_ip || ``;
}
let Fn = ref({}),
In = new Map(),
R = 0,
Ln = 0,
z = ref({}),
B = new Map();
function V(e) {
return (
z.value[e.id] ?? {
loading: !1,
error: ``,
flow: void 0,
}
);
}
async function Rn(e, t = !1) {
if (
e.module !== `kky_ecs` ||
e.status === `Unpaid` ||
e.status === `Deleted`
)
return;
if (B.has(e.id)) return B.get(e.id);
if (z.value[e.id]?.version === R && !t) return;
let n = R,
r = {
loading: !0,
error: ``,
flow: z.value[e.id]?.flow,
version: n,
};
z.value[e.id] = r;
let i = (async () => {
try {
let t = await b.get(`/kky_ecs/${e.id}/traffic`),
r =
!instance_data_d(`kky_ecs`, e, t).quota &&
(typeof t?.used != `number` ||
!Number.isFinite(t.used) ||
!t.start_time ||
!t.end_time)
? `流量统计暂不可用`
: ``;
n === R &&
(z.value[e.id] = {
loading: !1,
error: r,
flow: t,
version: n,
});
} catch (t) {
n === R &&
(z.value[e.id] = {
...r,
loading: !1,
error: t instanceof Error ? t.message : `流量获取失败`,
});
}
})();
B.set(e.id, i);
try {
await i;
} finally {
B.get(e.id) === i && B.delete(e.id);
}
}
function zn(e) {
let t = instance_data_a(e),
n = Fn.value[e.id];
return t.name ? t : instance_data_a(n?.raw);
}
function H(e) {
let t = Fn.value[e.id],
n = instance_data_d(
t?.module || e.module || ``,
{
...e,
...t?.raw,
},
z.value[e.id]?.flow ?? t?.raw?._flow,
);
return n.quota
? {
...n,
total: n.quota.total,
used: n.quota.used,
remaining: n.quota.remaining,
percent: n.quota.percent,
packageRemaining: n.quota.remaining,
reset: n.quota.end,
periodStart: ``,
periodEnd: ``,
usedLabel: `已用流量`,
unlimited: !1,
}
: n;
}
async function Bn(e) {
let t = R;
if (!(Fn.value[e.id]?.version === t || In.has(e.id))) {
In.set(e.id, t);
try {
if (!e.module && ![`Unpaid`, `Deleted`].includes(e.status)) {
let n = await b.get(`/host/${e.id}/view`);
if (t !== R || !n.module) return;
e.module = n.module;
}
if (
![
`kky_ecs`,
`mf_cloud`,
`mf_dcim`,
`remf_dcim`,
`idcsmart_common`,
`mf_finance`,
`remf_finance`,
].includes(e.module || ``)
)
return;
let n = [
`idcsmart_common`,
`mf_finance`,
`remf_finance`,
].includes(e.module || ``)
? `remf_finance`
: e.module;
if ((e.module === `kky_ecs` && Rn(e), n === `mf_cloud`)) {
let [r, i] = await Promise.all([
instance_data_a(e).name
? Promise.resolve({})
: b.get(`/mf_cloud/${e.id}`).catch(() => ({})),
b.get(`/mf_cloud/${e.id}/flow`).catch(() => null),
]);
t === R &&
(Fn.value[e.id] = {
module: n,
raw: {
...r,
_flow: i,
},
version: t,
});
return;
}
let r = await b.get(`/${n}/${e.id}`).catch(async (t) => {
if (e.module !== `idcsmart_common`) throw t;
let n = await b.get(
`/idcsmart_common/host/${e.id}/configoption`,
),
r = (
Array.isArray(n.configoptions) ? n.configoptions : []
).find((e) =>
[`操作系统`, `镜像版本`].includes(
configuration_display_t(e.option_name, e.option_type),
),
);
return {
...n,
os_name:
r?.subs
?.map((e) => e.option_name)
.filter(Boolean)
.join(` / `) || ``,
};
});
if (t !== R) return;
Fn.value[e.id] = {
module: n,
raw: r,
version: t,
};
} catch {
} finally {
In.get(e.id) === t && In.delete(e.id);
}
}
}
async function Vn(e) {
let t = ++Ln;
if (dn.value) return;
async function n(n) {
let r = 0;
await Promise.all(
Array.from(
{
length: Math.min(3, e.length),
},
async () => {
for (; t === Ln && r < e.length;) await n(e[r++]);
},
),
);
}
await Promise.all([n(Bn), n(Rn)]);
}
(watch(pn, (e) => {
Vn(e);
}),
onBeforeUnmount(() => {
(Ln++, R++);
}));
function Hn(e) {
e.id < 0 || Sn.value || (En(), navigateTo(Un(e.id)));
}
function Un(e) {
let t = m.modules.includes(`mf_cloud`)
? `cloud-servers`
: `dedicated-servers`;
return `/servers/server?id=${e}${m.menuId ? `&m=${m.menuId}&list=${t}` : ``}`;
}
let U = ref(null),
Wn = ref(``),
W = ref(!1),
G = ref(``);
function Gn(e) {
W.value ||
Sn.value ||
((U.value = e),
(Wn.value = e.client_notes || ``),
(G.value = ``));
}
function Kn() {
W.value || ((U.value = null), (G.value = ``));
}
async function qn() {
let e = U.value;
if (!e || W.value) return;
let t = Wn.value,
n = w.token;
((W.value = !0), (G.value = ``));
try {
if (
(await b.put(`/host/${e.id}/notes`, {
id: e.id,
notes: t,
}),
w.token !== n)
)
return;
e.client_notes = t;
let r = pn.value.find((t) => t.id === e.id);
(r && (r.client_notes = t),
E.invalidate(),
(U.value = null),
_n());
} catch (e) {
if (w.token !== n) return;
G.value = e instanceof Error ? e.message : `保存备注失败`;
} finally {
W.value = !1;
}
}
let Jn = [
{
action: `on`,
label: `开机`,
},
{
action: `off`,
label: `关机`,
},
{
action: `reboot`,
label: `重启`,
},
{
action: `hard_off`,
label: `强制关机`,
},
{
action: `hard_reboot`,
label: `强制重启`,
},
],
K = ref([]),
q = ref(``),
Yn = ref(``),
J = ref(null),
Y = 0,
X = !1;
onBeforeUnmount(() => {
X = !0;
});
let Z = ref([]),
Xn = computed(() =>
Z.value.some((e) => !e.success)
? Z.value.some((e) => e.success)
? `warn`
: `error`
: `success`,
),
Zn = ref(``),
Qn = ref(null),
$n = computed(() => [
...dr.value.map((e) => ({
label: e.label,
command: () => fr(e.action, e.label),
})),
{
label: `批量修改备注`,
icon: `pi pi-pencil`,
command: ar,
},
{
label: `批量续费`,
icon: `pi pi-calendar-plus`,
command: () => Dr(),
},
{
label: `按需计费(请在实例详情查看)`,
icon: `pi pi-clock`,
disabled: !0,
},
]),
er = ref(null),
tr = ref(``),
Q = ref(!1),
nr = ref(``),
rr = ref(``),
ir = ref(`success`);
function ar() {
if (X || Sn.value || q.value || Q.value) return;
let e = new Set(pn.value.map((e) => e.id)),
t = [
...new Set(
K.value
.map((e) => e.id)
.filter(
(t) => Number.isSafeInteger(t) && t > 0 && e.has(t),
),
),
];
t.length &&
((er.value = {
ids: t,
token: w.token,
epoch: Y,
}),
(tr.value = ``),
(nr.value = ``),
(rr.value = ``));
}
function or() {
Q.value || (er.value = null);
}
async function sr() {
let e = er.value;
if (!e || Q.value || X || e.token !== w.token || e.epoch !== Y)
return;
let t = () => !X && e.token === w.token && e.epoch === Y;
((Q.value = !0), (nr.value = ``));
try {
let n = await b.put(`/host/notes/batch`, {
ids: e.ids,
notes: tr.value,
});
if (!t()) return;
let r = Number(n?.success_count),
i = Number(n?.fail_count),
a = Number(n?.total);
if (
![r, i, a].every((e) => Number.isSafeInteger(e) && e >= 0) ||
a !== e.ids.length ||
r + i !== a
)
throw (
E.invalidate(),
_n(),
Error(`备注更新结果不完整,已刷新列表,请核对后重试`)
);
((ir.value = i ? `warn` : `success`),
(rr.value = `备注更新:成功 ${r} 台,失败 ${i} 台${i ? `。请核对列表后重新选择需要修改的实例` : ``}`),
(K.value = []),
(er.value = null),
E.invalidate(),
_n());
} catch (e) {
t() &&
(nr.value =
e instanceof Error ? e.message : `批量保存备注失败,请重试`);
} finally {
Q.value = !1;
}
}
function cr() {
K.value = [];
}
let lr = computed(() => {
let e = {};
for (let t of K.value) {
let n = t.module ?? ``;
t.status === `Active` && Ke(n) && (e[n] ??= []).push(t);
}
return e;
}),
ur = computed(
() =>
K.value.filter(
(e) => e.status !== `Active` || !Ke(e.module ?? ``),
).length,
),
dr = computed(() => {
let e = Object.keys(lr.value);
return e.length
? Jn.filter((t) =>
e.every((e) => Ke(e).actions.includes(t.action)),
)
: [];
});
function fr(e, t) {
X ||
Sn.value ||
q.value ||
!dr.value.some((t) => t.action === e) ||
((Yn.value = ``),
(Z.value = []),
(Zn.value = ``),
(J.value = {
action: e,
label: t,
hosts: K.value
.filter(
(t) =>
t.status === `Active` &&
Ke(t.module ?? ``)?.actions.includes(e),
)
.map((e) => ({
...e,
})),
skipped: ur.value,
token: w.token,
epoch: Y,
}));
}
function pr() {
q.value || (J.value = null);
}
function mr(e) {
(cr(), vn(e));
}
async function hr() {
let e = J.value;
if (
!e ||
X ||
q.value ||
!e.hosts.length ||
e.token !== w.token ||
e.epoch !== Y
)
return;
((q.value = e.action), (Yn.value = ``), (Z.value = []));
let t = Zn.value,
n = () => !X && e.token === w.token && e.epoch === Y,
r = {},
i = 0,
a = e.skipped,
o = new Set();
try {
for (let t of e.hosts) {
if (!n()) return;
try {
let i = await b.get(`/host/${t.id}/view`);
if (!n()) return;
let a = qe(i.module);
if (!a?.actions.includes(e.action))
throw Error(`实例管理接口不支持此操作,请进入实例详情核对`);
(r[a.path] ??= []).push(t);
} catch (e) {
if (!n()) return;
(o.add(t.id),
Z.value.push({
ids: [t.id],
success: !1,
message:
e instanceof Error
? e.message
: `实例管理接口加载失败,请重试`,
}));
}
}
for (let [s, c] of Object.entries(r)) {
if (!n()) return;
let r = c.filter((e) => e.status === `Active`).map((e) => e.id);
if (((a += c.length - r.length), !r.length)) continue;
let l = {
id: r,
action: e.action,
};
t && (l.client_operate_password = t);
try {
let e = await b.post(s, l);
if (!n()) return;
for (let t of Je(e, r))
(t.success
? (i += t.ids.length)
: t.ids.forEach((e) => o.add(e)),
Z.value.push({
...t,
message:
sanitizeMessage(t.message) ||
(t.success ? `指令已下发` : `指令下发失败`),
}));
} catch (e) {
if (!n()) return;
(r.forEach((e) => o.add(e)),
Z.value.push({
ids: r,
success: !1,
message: e instanceof Error ? e.message : `指令下发失败`,
}));
}
}
((J.value = null),
(Yn.value =
`已对 ${i} 台实例下发「${e.label}」指令` +
(o.size
? `,${o.size} 台下发失败;已仅保留失败实例的选择,可核对后重试`
: ``) +
(a
? `,另有 ${a} 台不支持批量操作或当前状态不可操作,已跳过`
: ``)),
(K.value = e.hosts.filter((e) => o.has(e.id))),
i &&
Cn.refreshAfterPower(
Z.value.filter((e) => e.success).flatMap((e) => e.ids),
));
} finally {
((q.value = ``), (Zn.value = ``));
}
}
let $ = ref(!1),
gr = ref(!1),
_r = ref([]),
vr = ref({}),
yr = ref({}),
br = ref(``),
xr = ref(!1),
Sr = ref(``),
Cr = ref(``),
wr = 0,
Tr = !1;
onBeforeUnmount(() => {
((Tr = !0), wr++);
});
let Er = computed(() =>
_r.value.filter((e) => e.renew_forbidden !== 1),
);
async function Dr() {
if (xr.value || Tr) return;
let e = ++wr,
t = K.value.map((e) => e.id),
n = () =>
!Tr &&
$.value &&
e === wr &&
JSON.stringify(t) === JSON.stringify(K.value.map((e) => e.id));
(($.value = !0),
(gr.value = !0),
(Sr.value = ``),
(Cr.value = ``),
(_r.value = []),
(vr.value = {}),
(yr.value = {}),
(br.value = ``));
try {
let e = await renewal_quote_t(
() =>
b.get(`/host/renew/batch`, {
ids: t,
}),
n,
);
if (!n()) return;
_r.value = (e.list ?? []).map((e) => ({
...e,
billing_cycles: renewal_quote_r(e.billing_cycles),
}));
for (let e of _r.value) {
let t =
e.billing_cycles?.find((e) => e.is_current_cycle === 1) ??
e.billing_cycles?.[0];
t && (vr.value[e.id] = t.billing_cycle);
}
} catch (e) {
n() && (Sr.value = renewal_quote_n(e));
} finally {
e === wr && (gr.value = !1);
}
}
function Or(e, t) {
return e.billing_cycles?.find((e) => e.billing_cycle === t);
}
let kr = computed(() =>
Er.value.reduce(
(e, t) => e + Number(Or(t, vr.value[t.id] ?? ``)?.price ?? 0),
0,
),
),
Ar = ref(null);
async function jr() {
if (Er.value.length) {
((xr.value = !0), (Sr.value = ``), (Cr.value = ``));
try {
let e = Object.fromEntries(
Object.entries(yr.value)
.map(([e, t]) => [e, t.trim()])
.filter(([, e]) => e),
),
t = {
ids: Er.value.map((e) => e.id),
billing_cycles: {
...vr.value,
},
};
(Object.keys(e).length &&
(t.customfield = {
promo_code: e,
}),
br.value && (t.client_operate_password = br.value));
let n = await b.post(`/host/renew/batch`, t, !0);
(($.value = !1),
(K.value = []),
n.code === `Unpaid` && n.data?.id
? ((Ar.value = {
id: n.data.id,
}),
(Nr.value = !0))
: ((Mr.value = `已为 ${Er.value.length} 台实例创建续费`),
setTimeout(() => (Mr.value = ``), 5e3)),
await Dn());
} catch (e) {
Cr.value = e instanceof Error ? e.message : `续费失败`;
} finally {
((xr.value = !1), (br.value = ``));
}
}
}
let Mr = ref(``),
Nr = ref(!1),
Pr = ref(null);
function Fr() {
((Mr.value = `续费成功`),
setTimeout(() => (Mr.value = ``), 5e3),
Dn());
}
return (
watch(Nr, (e) => {
e && Ar.value && (Pr.value = Ar.value.id);
}),
(e, r) => {
let a = ListSegments,
s = inputtext,
u = button,
p = ListEmpty,
b = column,
C = skeleton,
ie = NuxtLink,
ae = OsIcon,
oe = tag,
w = datatable,
Ee = OperationNotice,
De = menu,
Oe = paginator,
Pe = message,
Fe = textarea,
Ie = dialog,
Be = password,
Ve = OperatePasswordGate,
He = select,
Ue = PaymentDialog;
return (
openBlock(),
createElementBlock(`div`, Ye, [
createElementVNode(`div`, Xe, [
createElementVNode(`div`, null, [
createElementVNode(
`h2`,
null,
toDisplayString(c.title),
1,
),
]),
createElementVNode(`div`, Ze, [
renderSlot(e.$slots, `actions`, {}, void 0, !0),
]),
]),
createElementVNode(`div`, Qe, [
createVNode(
a,
{
modelValue: unref(A),
"onUpdate:modelValue": [
(r[0] ||= (e) => (isRef(A) ? (A.value = e) : null)),
An,
],
options: unref(ln),
},
null,
8,
[`modelValue`, `options`],
),
createElementVNode(`div`, $e, [
createElementVNode(
`form`,
{
class: `host-search`,
role: `search`,
"aria-label": `搜索${c.title}`,
onSubmit: withModifiers(kn, [`prevent`]),
},
[
createVNode(
s,
{
modelValue: unref(j),
"onUpdate:modelValue": (r[1] ||= (e) =>
isRef(j) ? (j.value = e) : null),
class: `list-search`,
placeholder: `搜索实例`,
"aria-label": `${c.title}搜索关键字`,
},
null,
8,
[`modelValue`, `aria-label`],
),
createVNode(
u,
{
type: `submit`,
label: `搜索`,
icon: `pi pi-search`,
size: `small`,
disabled: unref(P),
},
null,
8,
[`disabled`],
),
],
40,
et,
),
unref(Nn)
? (openBlock(),
createBlock(u, {
key: 0,
label: `清除筛选`,
icon: `pi pi-filter-slash`,
severity: `secondary`,
text: ``,
size: `small`,
onClick: jn,
}))
: createCommentVNode(``, !0),
]),
]),
createElementVNode(
`div`,
{
class: `list-table`,
"aria-busy": unref(P) || unref(L),
},
[
unref(L)
? (openBlock(),
createElementBlock(`span`, nt, `正在读取服务器列表`))
: createCommentVNode(``, !0),
unref(F) && !unref(hn) && !unref(P)
? (openBlock(),
createBlock(
p,
{
key: 1,
icon: `pi pi-exclamation-circle`,
title: `服务器加载失败`,
description: unref(F),
},
{
default: withCtx(() => [
createVNode(u, {
label: `重新加载`,
icon: `pi pi-refresh`,
severity: `secondary`,
size: `small`,
onClick: Dn,
}),
]),
_: 1,
},
8,
[`description`],
))
: (openBlock(),
createBlock(
w,
{
key: 2,
value: unref(xn),
loading: unref(P) && !unref(L),
inert: unref(L) || void 0,
"aria-hidden": unref(L) || void 0,
lazy: ``,
rows: unref(I),
totalRecords: unref(mn),
first: (unref(gn) - 1) * unref(I),
sortField: unref(M),
sortOrder: unref(N),
selection: unref(K),
"onUpdate:selection": (r[2] ||= (e) =>
isRef(K) ? (K.value = e) : null),
dataKey: `id`,
"row-class": () => `clickable`,
onSort: Mn,
onRowClick: (r[3] ||= (e) => Hn(e.data)),
},
{
empty: withCtx(() => [
createVNode(
p,
{
icon: `pi pi-server`,
title: unref(P)
? `加载中…`
: unref(Nn)
? `未找到匹配的服务器`
: `还没有服务器`,
description: unref(P)
? `正在读取服务器列表`
: unref(Nn)
? `换个搜索词或清除筛选条件后重试`
: `开通后可以在这里管理${c.title}`,
},
{
default: withCtx(() => [
!unref(P) && unref(Nn)
? (openBlock(),
createBlock(u, {
key: 0,
label: `清除筛选`,
icon: `pi pi-filter-slash`,
severity: `secondary`,
size: `small`,
onClick: jn,
}))
: unref(P)
? createCommentVNode(``, !0)
: (openBlock(),
createBlock(
ie,
{
key: 1,
to: `/products`,
class: `catalog-empty-action`,
},
{
default: withCtx(() => [
...(r[14] ||= [
createElementVNode(
`i`,
{
class: `pi pi-plus`,
"aria-hidden": `true`,
},
null,
-1,
),
createTextVNode(
`订购产品 `,
-1,
),
]),
]),
_: 1,
},
)),
]),
_: 1,
},
8,
[`title`, `description`],
),
]),
default: withCtx(() => [
unref(L)
? (openBlock(),
createBlock(
b,
{
key: 1,
style: {
width: `48px`,
},
},
{
body: withCtx(() => [
createVNode(C, {
width: `18px`,
height: `18px`,
}),
]),
_: 1,
},
))
: (openBlock(),
createBlock(b, {
key: 0,
selectionMode: `multiple`,
style: {
width: `48px`,
},
exportable: !1,
})),
createVNode(
b,
{
field: `id`,
header: `ID`,
sortable: ``,
style: {
width: `110px`,
},
},
{
body: withCtx(({ data: e }) => [
e.__skeleton
? (openBlock(),
createBlock(C, {
key: 0,
width: `4rem`,
height: `1.25rem`,
}))
: (openBlock(),
createBlock(
ie,
{
key: 1,
to: Un(e.id),
class: `col-id host-detail-link`,
"aria-label": `查看实例 #${e.id} 详情`,
onClick: withModifiers(En, [
`stop`,
]),
},
{
default: withCtx(() => [
createTextVNode(
`#` + toDisplayString(e.id),
1,
),
]),
_: 2,
},
1032,
[`to`, `aria-label`],
)),
]),
_: 1,
},
),
!unref(dn) && k(`ip`)
? (openBlock(),
createBlock(
b,
{
key: 2,
field: `dedicate_ip`,
header: `IP`,
sortable: ``,
style: {
width: `140px`,
},
},
{
body: withCtx(({ data: e }) => [
e.__skeleton
? (openBlock(),
createBlock(C, {
key: 0,
width: `7rem`,
height: `1.25rem`,
}))
: Pn(e)
? (openBlock(),
createElementBlock(
`span`,
rt,
toDisplayString(Pn(e)),
1,
))
: (openBlock(),
createElementBlock(
`span`,
it,
`—`,
)),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
createVNode(
b,
{
field: `name`,
header: `产品编号`,
sortable: ``,
style: {
"min-width": `180px`,
},
},
{
body: withCtx(({ data: e }) => [
e.__skeleton
? (openBlock(),
createBlock(C, {
key: 0,
width: `8rem`,
height: `1.25rem`,
}))
: (openBlock(),
createBlock(
ie,
{
key: 1,
to: Un(e.id),
class: `col-mono host-detail-link host-name`,
"aria-label": `查看 ${e.name || `未命名实例`}(#${e.id})详情`,
onClick: withModifiers(En, [
`stop`,
]),
},
{
default: withCtx(() => [
createTextVNode(
toDisplayString(
e.name || `未命名实例`,
),
1,
),
]),
_: 2,
},
1032,
[`to`, `aria-label`],
)),
]),
_: 1,
},
),
m.menuId && k(`area`)
? (openBlock(),
createBlock(
b,
{
key: 3,
header: `地域`,
style: {
"min-width": `180px`,
},
},
{
body: withCtx(({ data: e }) => [
e.__skeleton
? (openBlock(),
createBlock(C, {
key: 0,
width: `8rem`,
height: `1.25rem`,
}))
: (openBlock(),
createElementBlock(
`span`,
at,
toDisplayString(an(e)),
1,
)),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
k(`product_name`)
? (openBlock(),
createBlock(
b,
{
key: 4,
header: `名称`,
style: {
"min-width": `190px`,
},
},
{
body: withCtx(({ data: e }) => [
e.__skeleton
? (openBlock(),
createElementBlock(`div`, ot, [
createVNode(C, {
width: `8rem`,
height: `1.25rem`,
}),
createVNode(C, {
width: `5rem`,
height: `1.125rem`,
}),
]))
: (openBlock(),
createElementBlock(`div`, st, [
createElementVNode(
`div`,
null,
toDisplayString(
unref(product_name_n)(
e.product_name,
) || `—`,
),
1,
),
!m.menuId ||
!Array.isArray(
unref(D)?.select_field,
)
? (openBlock(),
createElementBlock(
`button`,
{
key: 0,
type: `button`,
class: `host-notes-edit`,
"aria-label": `编辑 ${unref(product_name_n)(e.product_name) || e.name || `实例`}(#${e.id})的备注`,
title:
e.client_notes ||
`添加备注`,
disabled: unref(Sn),
onClick: withModifiers(
(t) => Gn(e),
[`stop`],
),
},
[
createElementVNode(
`span`,
lt,
toDisplayString(
e.client_notes ||
`添加备注`,
),
1,
),
(r[15] ||=
createElementVNode(
`i`,
{
class: `pi pi-pencil`,
"aria-hidden": `true`,
},
null,
-1,
)),
],
8,
ct,
))
: createCommentVNode(``, !0),
])),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
m.menuId && k(`billing_cycle`)
? (openBlock(),
createBlock(
b,
{
key: 5,
header: `计费方式`,
style: {
"min-width": `140px`,
},
},
{
body: withCtx(({ data: e }) => [
e.__skeleton
? (openBlock(),
createBlock(C, {
key: 0,
width: `6rem`,
height: `1.25rem`,
}))
: (openBlock(),
createElementBlock(
`span`,
ut,
toDisplayString(
e.billing_cycle_name ||
e.billing_cycle ||
`—`,
),
1,
)),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
m.menuId && k(`is_auto_renew`)
? (openBlock(),
createBlock(
b,
{
key: 6,
header: `自动续费`,
style: {
"min-width": `110px`,
},
},
{
body: withCtx(({ data: e }) => [
e.__skeleton
? (openBlock(),
createBlock(C, {
key: 0,
width: `4rem`,
height: `1.25rem`,
}))
: (openBlock(),
createElementBlock(
`span`,
dt,
toDisplayString(
Number(e.is_auto_renew) === 1
? `已开启`
: `未开启`,
),
1,
)),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
m.menuId && k(`base_info`)
? (openBlock(),
createBlock(
b,
{
key: 7,
header: `基础信息`,
style: {
"min-width": `180px`,
},
},
{
body: withCtx(({ data: e }) => [
e.__skeleton
? (openBlock(),
createBlock(C, {
key: 0,
width: `8rem`,
height: `1.25rem`,
}))
: (openBlock(),
createElementBlock(
`span`,
ft,
toDisplayString(
(Number(e.show_base_info) ===
1 &&
e.base_info) ||
`—`,
),
1,
)),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
(openBlock(!0),
createElementBlock(
Fragment,
null,
renderList(
unref(D)?.self_defined_field ?? [],
(e) => (
openBlock(),
createBlock(
b,
{
key: `custom-${e.id}`,
header: e.field_name,
style: {
"min-width": `150px`,
},
},
{
body: withCtx(({ data: n }) => [
n.__skeleton
? (openBlock(),
createBlock(C, {
key: 0,
width: `6rem`,
height: `1.25rem`,
}))
: (openBlock(),
createElementBlock(
`span`,
pt,
toDisplayString(on(n, e)),
1,
)),
]),
_: 2,
},
1032,
[`header`],
)
),
),
128,
)),
!unref(dn) && k(`traffic`)
? (openBlock(),
createBlock(
b,
{
key: 8,
header: `流量`,
style: {
"min-width": `245px`,
},
},
{
body: withCtx(({ data: e }) => [
e.__skeleton
? (openBlock(),
createElementBlock(`div`, mt, [
createVNode(C, {
width: `11rem`,
height: `0.5rem`,
}),
createVNode(C, {
width: `8rem`,
height: `1.125rem`,
}),
]))
: (openBlock(),
createElementBlock(
`div`,
{
key: 1,
class: `host-traffic`,
"aria-busy": V(e).loading,
},
[
H(e).unlimited
? (openBlock(),
createElementBlock(
`div`,
gt,
[
(r[17] ||=
createElementVNode(
`span`,
{
class: `traffic-infinity`,
"aria-hidden": `true`,
},
`∞`,
-1,
)),
createElementVNode(
`div`,
_t,
[
(r[16] ||=
createElementVNode(
`span`,
{
class: `traffic-unlimited-label`,
},
`不限流量`,
-1,
)),
createElementVNode(
`small`,
{
class: `muted`,
title: H(e)
.periodStart
? `${H(e).periodStart} 至 ${H(e).periodEnd}`
: void 0,
},
toDisplayString(
H(e).used ===
null
? `无流量额度限制`
: `${H(e).usedLabel} ${H(e).periodStart ? unref(instance_data_r)(H(e).used) : unref(instance_data_n)(H(e).used)}`,
),
9,
vt,
),
],
),
],
))
: (openBlock(),
createElementBlock(
Fragment,
{
key: 1,
},
[
H(e).percent === null
? H(e).periodStart
? (openBlock(),
createElementBlock(
`div`,
{
key: 1,
class: `traffic-period`,
title: `${H(e).periodStart} 至 ${H(e).periodEnd}`,
},
[
...(r[18] ||=
[
createElementVNode(
`i`,
{
class: `pi pi-clock`,
"aria-hidden": `true`,
},
null,
-1,
),
createTextVNode(
`最近完整小时 `,
-1,
),
]),
],
8,
bt,
))
: createCommentVNode(
``,
!0,
)
: (openBlock(),
createElementBlock(
`div`,
{
key: 0,
class: `traffic-track`,
role: `progressbar`,
"aria-label": `流量使用比例`,
"aria-valuenow":
H(e)
.percent,
"aria-valuemin": 0,
"aria-valuemax": 100,
"aria-valuetext": `已用流量 ${unref(instance_data_n)(H(e).used)},总额度 ${unref(instance_data_n)(H(e).total)}`,
title: `总额度 ${unref(instance_data_n)(H(e).total)}`,
},
[
createElementVNode(
`div`,
{
class: `traffic-track-fill`,
style:
normalizeStyle(
{
width: `${H(e).percent}%`,
},
),
},
null,
4,
),
],
8,
yt,
)),
H(e).used === null
? createCommentVNode(
``,
!0,
)
: (openBlock(),
createElementBlock(
`div`,
{
key: 2,
class: `traffic-usage`,
title: H(e)
.periodStart
? `${H(e).usedLabel}:${H(e).periodStart} 至 ${H(e).periodEnd}`
: void 0,
},
[
(r[19] ||=
createElementVNode(
`i`,
{
class: `pi pi-arrow-right-arrow-left`,
"aria-hidden": `true`,
},
null,
-1,
)),
createElementVNode(
`span`,
null,
[
createTextVNode(
toDisplayString(
H(e)
.periodStart
? `出站流量`
: `已用流量`,
) +
` ` +
toDisplayString(
H(e)
.periodStart
? unref(
instance_data_r,
)(
H(
e,
)
.used,
)
: unref(
instance_data_n,
)(
H(
e,
)
.used,
),
),
1,
),
H(e)
.percent ===
null
? createCommentVNode(
``,
!0,
)
: (openBlock(),
createElementBlock(
Fragment,
{
key: 0,
},
[
createTextVNode(
` (` +
toDisplayString(
H(
e,
).percent.toFixed(
0,
),
) +
`%)`,
1,
),
],
64,
)),
],
),
],
8,
xt,
)),
H(e)
.packageRemaining ===
null
? H(e).used ===
null &&
!V(e).loading &&
!V(e).error
? (openBlock(),
createElementBlock(
`span`,
Ct,
toDisplayString(
H(e).metered
? `按流量计费`
: e.module ===
`kky_ecs` &&
unref(
Fn,
)[
e.id
]
? `按带宽计费`
: `—`,
),
1,
))
: createCommentVNode(
``,
!0,
)
: (openBlock(),
createElementBlock(
`span`,
St,
`流量包剩余 ` +
toDisplayString(
unref(
instance_data_n,
)(
H(e)
.packageRemaining,
),
),
1,
)),
],
64,
)),
V(e).loading && !V(e).flow
? (openBlock(),
createElementBlock(
`span`,
wt,
`正在加载流量…`,
))
: V(e).error
? (openBlock(),
createElementBlock(
`span`,
Tt,
[
createElementVNode(
`span`,
{
title:
V(e).error,
},
`流量获取失败`,
8,
Et,
),
createVNode(
u,
{
label: `重试`,
size: `small`,
text: ``,
onClick:
withModifiers(
(t) =>
Rn(e, !0),
[`stop`],
),
},
null,
8,
[`onClick`],
),
],
))
: createCommentVNode(
``,
!0,
),
],
8,
ht,
)),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
m.menuId && k(`active_time`)
? (openBlock(),
createBlock(
b,
{
key: 9,
header: `开通时间`,
style: {
"min-width": `150px`,
"white-space": `nowrap`,
},
},
{
body: withCtx(({ data: n }) => [
n.__skeleton
? (openBlock(),
createBlock(C, {
key: 0,
width: `7rem`,
height: `1.25rem`,
}))
: (openBlock(),
createElementBlock(
`span`,
Dt,
toDisplayString(
n.active_time
? (`formatTime` in e
? e.formatTime
: unref(dict_r))(
n.active_time,
)
: `—`,
),
1,
)),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
k(`due_time`)
? (openBlock(),
createBlock(
b,
{
key: 10,
field: `due_time`,
header: `到期时间`,
sortable: ``,
style: {
"min-width": `150px`,
"white-space": `nowrap`,
},
},
{
body: withCtx(({ data: n }) => [
n.__skeleton
? (openBlock(),
createBlock(C, {
key: 0,
width: `7rem`,
height: `1.25rem`,
}))
: n.due_time
? (openBlock(),
createElementBlock(
`span`,
Ot,
toDisplayString(
(`formatTime` in e
? e.formatTime
: unref(dict_r))(
n.due_time,
),
),
1,
))
: (openBlock(),
createElementBlock(
`span`,
kt,
`—`,
)),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
!unref(dn) && k(`os`)
? (openBlock(),
createBlock(
b,
{
key: 11,
header: `操作系统`,
style: {
width: `80px`,
"min-width": `80px`,
},
},
{
body: withCtx(({ data: t }) => [
t.__skeleton
? (openBlock(),
createBlock(C, {
key: 0,
width: `24px`,
height: `24px`,
}))
: (openBlock(),
createElementBlock(
`div`,
{
key: 1,
class: `os-cell`,
role: `img`,
"aria-label":
unref(os_name_t)(
zn(t).name,
) || `镜像信息暂未返回`,
title:
unref(os_name_t)(
zn(t).name,
) || `镜像信息暂未返回`,
},
[
createVNode(
ae,
{
url:
zn(t).url ||
(`osIconUrl` in e
? e.osIconUrl
: unref(modules_n))(
zn(t).icon,
t.module,
zn(t).name,
),
name: zn(t).name,
size: 24,
"aria-hidden": `true`,
},
null,
8,
[`url`, `name`],
),
],
8,
At,
)),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
k(`status`)
? (openBlock(),
createBlock(
b,
{
key: 12,
header: `产品状态`,
style: {
width: `110px`,
},
},
{
body: withCtx(({ data: t }) => [
t.__skeleton
? (openBlock(),
createBlock(C, {
key: 0,
width: `4rem`,
height: `1.5rem`,
borderRadius: `20px`,
}))
: (openBlock(),
createBlock(
oe,
{
key: 1,
class: `instance-product-status`,
value:
m.menuId &&
Array.isArray(
unref(D)?.select_field,
)
? (`statusLabel` in e
? e.statusLabel
: unref(dict_c))(
t.status,
)
: unref(wn)(t).label,
severity:
m.menuId &&
Array.isArray(
unref(D)?.select_field,
)
? (`statusSeverity` in e
? e.statusSeverity
: unref(dict_l))(
t.status,
)
: unref(wn)(t).severity,
},
null,
8,
[`value`, `severity`],
)),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
m.menuId &&
Array.isArray(unref(D)?.select_field) &&
k(`notes`)
? (openBlock(),
createBlock(
b,
{
key: 13,
header: `备注`,
style: {
"min-width": `190px`,
},
},
{
body: withCtx(({ data: e }) => [
e.__skeleton
? (openBlock(),
createBlock(C, {
key: 0,
width: `8rem`,
height: `1.25rem`,
}))
: (openBlock(),
createElementBlock(
`button`,
{
key: 1,
type: `button`,
class: `host-notes-edit`,
"aria-label": `编辑 ${unref(product_name_n)(e.product_name) || e.name || `实例`}(#${e.id})的备注`,
title:
e.client_notes ||
`添加备注`,
disabled: unref(Sn),
onClick: withModifiers(
(t) => Gn(e),
[`stop`],
),
},
[
createElementVNode(
`span`,
Mt,
toDisplayString(
e.client_notes ||
`添加备注`,
),
1,
),
(r[20] ||= createElementVNode(
`i`,
{
class: `pi pi-pencil`,
"aria-hidden": `true`,
},
null,
-1,
)),
],
8,
jt,
)),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
]),
_: 1,
},
8,
[
`value`,
`loading`,
`inert`,
`aria-hidden`,
`rows`,
`totalRecords`,
`first`,
`sortField`,
`sortOrder`,
`selection`,
],
)),
],
8,
tt,
),
unref(xn).length
? (openBlock(),
createElementBlock(`p`, Nt, [
...(r[21] ||= [
createElementVNode(
`i`,
{
class: `pi pi-arrows-h`,
"aria-hidden": `true`,
},
null,
-1,
),
createTextVNode(`左右滑动查看完整实例信息`, -1),
]),
]))
: createCommentVNode(``, !0),
unref(Yn)
? (openBlock(),
createBlock(
Ee,
{
key: 1,
severity: unref(Xn),
message: unref(Yn),
details: unref(Z).map(
(e) =>
`实例 ${e.ids.map((e) => `#${e}`).join(`、`)}:${e.message}`,
),
},
null,
8,
[`severity`, `message`, `details`],
))
: createCommentVNode(``, !0),
unref(Mr)
? (openBlock(),
createBlock(
Ee,
{
key: 2,
message: unref(Mr),
},
null,
8,
[`message`],
))
: createCommentVNode(``, !0),
unref(Cr)
? (openBlock(),
createBlock(
Ee,
{
key: 3,
severity: `error`,
message: unref(Cr),
},
null,
8,
[`message`],
))
: createCommentVNode(``, !0),
unref(rr)
? (openBlock(),
createBlock(
Ee,
{
key: 4,
severity: unref(ir),
message: unref(rr),
},
null,
8,
[`severity`, `message`],
))
: createCommentVNode(``, !0),
createElementVNode(
`div`,
{
class: normalizeClass([
`list-foot host-list-foot`,
{
"host-list-foot-empty": !unref(L) && !unref(mn),
},
]),
inert: unref(L) || !unref(mn) || void 0,
},
[
createElementVNode(`div`, Ft, [
createVNode(
u,
{
label: `批量操作`,
size: `small`,
disabled:
unref(Sn) ||
!unref(K).length ||
!!unref(q) ||
unref(Q),
loading: !!unref(q) || unref(Q),
"aria-haspopup": `menu`,
"aria-controls": `host-batch-menu`,
onClick: (r[4] ||= (e) => unref(Qn)?.toggle(e)),
},
null,
8,
[`disabled`, `loading`],
),
createVNode(
De,
{
id: `host-batch-menu`,
ref_key: `batchMenu`,
ref: Qn,
model: unref($n),
popup: ``,
},
null,
8,
[`model`],
),
unref(K).length
? (openBlock(),
createElementBlock(
`span`,
It,
`已选 ` +
toDisplayString(unref(K).length) +
` 台`,
1,
))
: createCommentVNode(``, !0),
]),
createVNode(
Oe,
{
rows: unref(I),
totalRecords: unref(L)
? unref(gn) * unref(I)
: unref(mn),
first: (unref(gn) - 1) * unref(I),
rowsPerPageOptions: [10, 20, 50, 100, 200],
onPage: mr,
},
null,
8,
[`rows`, `totalRecords`, `first`],
),
],
10,
Pt,
),
unref(F) && unref(hn)
? (openBlock(),
createBlock(
Pe,
{
key: 5,
severity: `warn`,
closable: !1,
class: `host-refresh-error`,
},
{
default: withCtx(() => [
createElementVNode(
`span`,
null,
`刷新失败,当前显示上次成功加载的数据。` +
toDisplayString(unref(F)),
1,
),
createVNode(
u,
{
label: `重试`,
icon: `pi pi-refresh`,
severity: `secondary`,
size: `small`,
disabled: unref(P),
onClick: Dn,
},
null,
8,
[`disabled`],
),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
createVNode(
Ie,
{
visible: !!unref(er),
header: `批量修改备注`,
modal: ``,
draggable: !1,
closable: !unref(Q),
"close-on-escape": !unref(Q),
style: {
width: `448px`,
maxWidth: `calc(100vw - 32px)`,
},
"onUpdate:visible": (r[6] ||= (e) => {
e || or();
}),
},
{
footer: withCtx(() => [
createVNode(
u,
{
label: `取消`,
severity: `secondary`,
text: ``,
disabled: unref(Q),
onClick: or,
},
null,
8,
[`disabled`],
),
createVNode(
u,
{
label: `确认保存`,
loading: unref(Q),
disabled: unref(Q),
onClick: sr,
},
null,
8,
[`loading`, `disabled`],
),
]),
default: withCtx(() => [
createElementVNode(`div`, Lt, [
createElementVNode(
`p`,
Rt,
`将覆盖所选 ` +
toDisplayString(unref(er)?.ids.length) +
` 台实例的备注。留空并保存会清空备注。`,
1,
),
(r[22] ||= createElementVNode(
`label`,
{
for: `host-batch-notes`,
},
`备注`,
-1,
)),
createVNode(
Fe,
{
id: `host-batch-notes`,
modelValue: unref(tr),
"onUpdate:modelValue": (r[5] ||= (e) =>
isRef(tr) ? (tr.value = e) : null),
rows: `3`,
autoResize: ``,
fluid: ``,
disabled: unref(Q),
"aria-invalid": !!unref(nr),
},
null,
8,
[`modelValue`, `disabled`, `aria-invalid`],
),
unref(nr)
? (openBlock(),
createBlock(
Ee,
{
key: 0,
severity: `error`,
message: unref(nr),
},
null,
8,
[`message`],
))
: createCommentVNode(``, !0),
]),
]),
_: 1,
},
8,
[`visible`, `closable`, `close-on-escape`],
),
createVNode(
Ie,
{
visible: !!unref(U),
header: `编辑备注`,
modal: ``,
style: {
width: `448px`,
maxWidth: `calc(100vw - 32px)`,
},
draggable: !1,
closable: !unref(W),
"close-on-escape": !unref(W),
"onUpdate:visible": (r[8] ||= (e) => {
e || Kn();
}),
},
{
footer: withCtx(() => [
createVNode(
u,
{
label: `取消`,
severity: `secondary`,
text: ``,
disabled: unref(W),
onClick: Kn,
},
null,
8,
[`disabled`],
),
createVNode(
u,
{
label: `保存`,
loading: unref(W),
disabled: unref(W),
onClick: qn,
},
null,
8,
[`loading`, `disabled`],
),
]),
default: withCtx(() => [
createElementVNode(`div`, zt, [
createElementVNode(
`p`,
Bt,
toDisplayString(
unref(product_name_n)(unref(U)?.product_name) ||
unref(U)?.name,
) +
` · #` +
toDisplayString(unref(U)?.id),
1,
),
(r[23] ||= createElementVNode(
`label`,
{
for: `host-list-notes`,
},
`备注`,
-1,
)),
createVNode(
Fe,
{
id: `host-list-notes`,
modelValue: unref(Wn),
"onUpdate:modelValue": (r[7] ||= (e) =>
isRef(Wn) ? (Wn.value = e) : null),
rows: `3`,
autoResize: ``,
fluid: ``,
placeholder: `填写实例用途或备注(选填)`,
disabled: unref(W),
"aria-invalid": !!unref(G),
},
null,
8,
[`modelValue`, `disabled`, `aria-invalid`],
),
unref(G)
? (openBlock(),
createBlock(
Ee,
{
key: 0,
severity: `error`,
message: unref(G),
},
null,
8,
[`message`],
))
: createCommentVNode(``, !0),
]),
]),
_: 1,
},
8,
[`visible`, `closable`, `close-on-escape`],
),
createVNode(
Ie,
{
visible: !!unref(J),
header: `批量${unref(J)?.label ?? ``}`,
modal: ``,
style: {
width: `420px`,
},
draggable: !1,
closable: !unref(q),
"close-on-escape": !unref(q),
"onUpdate:visible": pr,
},
{
footer: withCtx(() => [
createVNode(
u,
{
label: `取消`,
severity: `secondary`,
text: ``,
disabled: !!unref(q),
onClick: pr,
},
null,
8,
[`disabled`],
),
createVNode(
u,
{
label: unref(J)?.label,
severity:
unref(J)?.action === `on` ? `success` : `danger`,
loading: !!unref(q),
disabled: !!unref(q),
onClick: hr,
},
null,
8,
[`label`, `severity`, `loading`, `disabled`],
),
]),
default: withCtx(() => [
createElementVNode(`div`, Vt, [
createElementVNode(`p`, Ht, [
(r[24] ||= createTextVNode(` 将对选中的 `, -1)),
createElementVNode(
`strong`,
null,
toDisplayString(unref(J)?.hosts.length),
1,
),
createTextVNode(
` 台实例下发「` +
toDisplayString(unref(J)?.label) +
`」指令。 `,
1,
),
unref(J)?.action === `on`
? createCommentVNode(``, !0)
: (openBlock(),
createElementBlock(
Fragment,
{
key: 0,
},
[
createTextVNode(
`操作可能中断服务,请确认已保存工作。`,
),
],
64,
)),
]),
unref(J)?.skipped
? (openBlock(),
createElementBlock(
`p`,
Ut,
`另有 ` +
toDisplayString(unref(J).skipped) +
` 台不支持批量操作或当前状态不可操作,将自动跳过。`,
1,
))
: createCommentVNode(``, !0),
createVNode(Ve, null, {
default: withCtx(() => [
createElementVNode(`div`, Wt, [
(r[25] ||= createElementVNode(
`label`,
{
for: `batch-op-pwd`,
},
`操作密码`,
-1,
)),
createVNode(
Be,
{
modelValue: unref(Zn),
"onUpdate:modelValue": (r[9] ||= (e) =>
isRef(Zn) ? (Zn.value = e) : null),
"input-id": `batch-op-pwd`,
feedback: !1,
toggleMask: ``,
disabled: !!unref(q),
placeholder: `账户已设置操作密码时必填`,
},
null,
8,
[`modelValue`, `disabled`],
),
]),
]),
_: 1,
}),
]),
]),
_: 1,
},
8,
[`visible`, `header`, `closable`, `close-on-escape`],
),
createVNode(
Ie,
{
visible: unref($),
"onUpdate:visible": (r[12] ||= (e) =>
isRef($) ? ($.value = e) : null),
header: `批量续费`,
modal: ``,
draggable: !1,
style: {
width: `720px`,
},
},
{
footer: withCtx(() => [
createVNode(u, {
label: `取消`,
severity: `secondary`,
text: ``,
onClick: (r[11] ||= (e) => ($.value = !1)),
}),
createVNode(
u,
{
label: `提交续费`,
loading: unref(xr),
disabled: !unref(Er).length,
onClick: jr,
},
null,
8,
[`loading`, `disabled`],
),
]),
default: withCtx(() => [
unref(gr)
? (openBlock(),
createElementBlock(`div`, Gt, [
createVNode(C, {
height: `160px`,
}),
]))
: (openBlock(),
createElementBlock(`div`, Kt, [
createElementVNode(
`p`,
qt,
` 共选 ` +
toDisplayString(unref(_r).length) +
` 台,其中可续费 ` +
toDisplayString(unref(Er).length) +
` 台。到期时间按所选周期顺延。 `,
1,
),
createVNode(
w,
{
value: unref(_r),
size: `small`,
scrollable: ``,
dataKey: `id`,
},
{
default: withCtx(() => [
createVNode(
b,
{
header: `产品`,
style: {
"min-width": `220px`,
},
},
{
body: withCtx(({ data: e }) => [
createElementVNode(`div`, Jt, [
createElementVNode(
`span`,
Yt,
toDisplayString(
unref(product_name_n)(
e.product_name,
),
),
1,
),
createElementVNode(
`span`,
Xt,
toDisplayString(e.name),
1,
),
]),
]),
_: 1,
},
),
createVNode(
b,
{
header: `到期时间`,
style: {
width: `150px`,
},
},
{
body: withCtx(({ data: n }) => [
createElementVNode(
`span`,
Zt,
toDisplayString(
(`formatTime` in e
? e.formatTime
: unref(dict_r))(n.due_time),
),
1,
),
]),
_: 1,
},
),
createVNode(
b,
{
header: `续费周期`,
style: {
width: `170px`,
},
},
{
body: withCtx(({ data: e }) => [
e.renew_forbidden === 1
? (openBlock(),
createBlock(oe, {
key: 1,
value: `不可续费`,
severity: `secondary`,
}))
: (openBlock(),
createBlock(
He,
{
key: 0,
modelValue: unref(vr)[e.id],
"onUpdate:modelValue": (t) =>
(unref(vr)[e.id] = t),
options: e.billing_cycles,
optionLabel: `name_show`,
optionValue: `billing_cycle`,
placeholder: `选择续费周期`,
class: `renew-select`,
},
null,
8,
[
`modelValue`,
`onUpdate:modelValue`,
`options`,
],
)),
]),
_: 1,
},
),
createVNode(
b,
{
header: `优惠码`,
style: {
width: `180px`,
},
},
{
body: withCtx(({ data: e }) => [
e.renew_forbidden === 1
? (openBlock(),
createElementBlock(
`span`,
Qt,
`—`,
))
: (openBlock(),
createBlock(
s,
{
key: 0,
modelValue: unref(yr)[e.id],
"onUpdate:modelValue": (t) =>
(unref(yr)[e.id] = t),
class: `renew-promo`,
placeholder: `该实例专属优惠码`,
disabled: unref(xr),
},
null,
8,
[
`modelValue`,
`onUpdate:modelValue`,
`disabled`,
],
)),
]),
_: 1,
},
),
createVNode(
b,
{
header: `金额`,
style: {
width: `110px`,
},
},
{
body: withCtx(({ data: e }) => [
e.renew_forbidden === 1
? (openBlock(),
createElementBlock(
`span`,
en,
`—`,
))
: (openBlock(),
createElementBlock(
`span`,
$t,
` ¥` +
toDisplayString(
Or(e, unref(vr)[e.id] ?? ``)
?.price ?? `0.00`,
),
1,
)),
]),
_: 1,
},
),
]),
_: 1,
},
8,
[`value`],
),
createElementVNode(`div`, tn, [
(r[26] ||= createTextVNode(` 合计 `, -1)),
createElementVNode(
`b`,
null,
`¥` + toDisplayString(unref(kr).toFixed(2)),
1,
),
]),
unref(Sr)
? (openBlock(),
createBlock(
Pe,
{
key: 0,
severity: `error`,
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(
toDisplayString(unref(Sr)),
1,
),
createVNode(
u,
{
label: `重新获取价格`,
size: `small`,
severity: `secondary`,
text: ``,
disabled: unref(xr),
onClick: Dr,
},
null,
8,
[`disabled`],
),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
createVNode(Ve, null, {
default: withCtx(() => [
createElementVNode(`div`, nn, [
(r[27] ||= createElementVNode(
`label`,
{
for: `batch-renew-operate-password`,
},
`操作密码`,
-1,
)),
createVNode(
Be,
{
modelValue: unref(br),
"onUpdate:modelValue": (r[10] ||= (
e,
) =>
isRef(br) ? (br.value = e) : null),
"input-id": `batch-renew-operate-password`,
feedback: !1,
toggleMask: ``,
placeholder: `账户已设置时填写`,
disabled: unref(xr),
},
null,
8,
[`modelValue`, `disabled`],
),
]),
]),
_: 1,
}),
(r[28] ||= createElementVNode(
`p`,
{
class: `renew-hint`,
},
`余额不足时会创建待支付订单,可在支付弹窗中完成付款。优惠码会按实例分别提交,最终金额以服务端订单为准。`,
-1,
)),
])),
]),
_: 1,
},
8,
[`visible`],
),
createVNode(
Ue,
{
modelValue: unref(Nr),
"onUpdate:modelValue": (r[13] ||= (e) =>
isRef(Nr) ? (Nr.value = e) : null),
"order-id": unref(Pr),
amount: String(unref(kr).toFixed(2)),
onSuccess: Fr,
},
null,
8,
[`modelValue`, `order-id`, `amount`],
),
])
);
}
);
},
}),
[[`__scopeId`, `data-v-e23fddb0`]],
),
{
__name: `HostList`,
},
);
export {};
export default rn;
</script>