前端验证 / verify (push) Failing after 15m3s
- 统一页面标题、圆角、字体和响应式断点,调整暗色主题及图表配色 - 新增表格列标签插件,在窄屏下将表格转换为卡片布局,优化实例、订单、工单等列表展示 - 支持移动端点击订单行进入详情,并完善订单凭据的打印布局 - 在财务中心展示本月及累计消费,补充充值关闭时的提示 - 优化工单详情布局,将附件上传入口整合至富文本编辑器工具栏 - 调整实例操作按钮、SSH 密钥操作及安全菜单图标 - 为多个页面显式导入 definePageMeta,完善页面元数据声明
3028 lines
123 KiB
Vue
3028 lines
123 KiB
Vue
<script>
|
||
/**
|
||
* 实例详情调度页:先确认主机与商品,再解析实际管理模块;统一展示数据与能力开关,云/物理/通用旧模块分别委派管理组件。权限展示不替代后端鉴权。
|
||
*/
|
||
import { definePageMeta } from "#imports";
|
||
import "~/assets/styles/InstanceLoadingShell.CwfiUwdU.css";
|
||
import "~/assets/styles/FlowPacketPanel.-RJSx13z.css";
|
||
import "~/assets/styles/InstanceServiceInfo.BftSVIeW.css";
|
||
import "~/assets/styles/CommonUpgrade.C8sZ-ExM.css";
|
||
import "~/assets/styles/LegacyProductUpgrade.dzWGwGgY.css";
|
||
import "~/assets/styles/RemfUpgrade.4stQ5ASH.css";
|
||
import "~/assets/styles/ChartBox.CYP_mhat.css";
|
||
import "~/assets/styles/CommonManage.qcc2l13i.css";
|
||
import "~/assets/styles/server.DGuhrprb.css";
|
||
definePageMeta({
|
||
key: (e) => e.fullPath,
|
||
});
|
||
import { toDisplayString } from "vue";
|
||
import { renderList } from "vue";
|
||
import { onMounted } from "vue";
|
||
import { onUnmounted } from "vue";
|
||
import { normalizeClass } from "vue";
|
||
import { watch } from "vue";
|
||
import { Suspense } from "vue";
|
||
import { defineAsyncComponent } 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 { 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 { publicAssetsURL } from "#internal/nuxt/paths";
|
||
import { NuxtLink } from "#components";
|
||
import { loadModule } from "~/utils/load-module.js";
|
||
import { useApi } 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 OperationNotice from "~/components/OperationNotice.vue";
|
||
import OperatePasswordGate from "~/components/OperatePasswordGate.vue";
|
||
import { t as interval_t } from "~/lib/interval.js";
|
||
import { n as instance_status_n } from "~/lib/instance-status.js";
|
||
import { r as instance_status_r } from "~/lib/instance-status.js";
|
||
import { t as instance_status_t } from "~/lib/instance-status.js";
|
||
import textarea from "primevue/textarea";
|
||
import menu from "primevue/menu";
|
||
import tag from "primevue/tag";
|
||
import skeleton from "primevue/skeleton";
|
||
import { n as server_page_n } from "~/lib/server-page.js";
|
||
import { a as instance_data_a } from "~/lib/instance-data.js";
|
||
import { c as instance_data_c } from "~/lib/instance-data.js";
|
||
import { i as instance_data_i } from "~/lib/instance-data.js";
|
||
import { l as instance_data_l } from "~/lib/instance-data.js";
|
||
import { t as instance_data_t } from "~/lib/instance-data.js";
|
||
import { u as instance_data_u } from "~/lib/instance-data.js";
|
||
import { n as configuration_display_n } from "~/lib/configuration-display.js";
|
||
import CommonManage from "~/components/instance/CommonManage.vue";
|
||
import { t as remote_console_t } from "~/lib/remote-console.js";
|
||
import InstanceServiceInfo from "~/components/instance/InstanceServiceInfo.vue";
|
||
import InstanceLoadingShell from "~/components/instance/InstanceLoadingShell.vue";
|
||
import { t as composables_t } from "~/lib/composables-2.js";
|
||
var M = {
|
||
jy_cloud: {
|
||
snapshot: !1,
|
||
rescue: !1,
|
||
hardPower: !1,
|
||
log: !1,
|
||
upgrade: !1,
|
||
traffic: !1,
|
||
disk: !1,
|
||
securityGroup: !1,
|
||
power: !0,
|
||
passwordReset: !0,
|
||
reinstall: !0,
|
||
remoteConsole: !1,
|
||
},
|
||
jy_dcim: {
|
||
snapshot: !1,
|
||
rescue: !1,
|
||
hardPower: !1,
|
||
log: !1,
|
||
upgrade: !1,
|
||
traffic: !1,
|
||
disk: !1,
|
||
securityGroup: !1,
|
||
power: !0,
|
||
passwordReset: !0,
|
||
reinstall: !0,
|
||
remoteConsole: !1,
|
||
},
|
||
remf_cloud: {
|
||
snapshot: !0,
|
||
rescue: !0,
|
||
hardPower: !0,
|
||
log: !0,
|
||
upgrade: !0,
|
||
traffic: !0,
|
||
securityGroup: !1,
|
||
power: !0,
|
||
passwordReset: !0,
|
||
reinstall: !0,
|
||
remoteConsole: !0,
|
||
},
|
||
mf_cloud: {
|
||
snapshot: !0,
|
||
rescue: !0,
|
||
hardPower: !0,
|
||
log: !0,
|
||
upgrade: !0,
|
||
traffic: !0,
|
||
securityGroup: !1,
|
||
power: !0,
|
||
passwordReset: !0,
|
||
reinstall: !0,
|
||
remoteConsole: !0,
|
||
},
|
||
kky_ecs: {
|
||
snapshot: !1,
|
||
rescue: !1,
|
||
hardPower: !1,
|
||
log: !1,
|
||
upgrade: !0,
|
||
traffic: !0,
|
||
securityGroup: !0,
|
||
power: !0,
|
||
passwordReset: !0,
|
||
reinstall: !0,
|
||
remoteConsole: !0,
|
||
},
|
||
remf_finance: {
|
||
snapshot: !0,
|
||
rescue: !0,
|
||
hardPower: !0,
|
||
log: !0,
|
||
upgrade: !0,
|
||
traffic: !0,
|
||
securityGroup: !1,
|
||
power: !0,
|
||
passwordReset: !0,
|
||
reinstall: !0,
|
||
remoteConsole: !0,
|
||
},
|
||
};
|
||
// 统一云实例数据、状态和磁盘访问;模块变化或作用域销毁时递增请求代次,使旧模块在途响应失效。
|
||
function Ee(e, t, n) {
|
||
let r = useApi(),
|
||
i = ref(null),
|
||
o = ref(``),
|
||
s = ref(null),
|
||
l = ref(!1),
|
||
d = ref(``),
|
||
f = ref(!1),
|
||
m = ref(``),
|
||
h = ref(!1),
|
||
g = ref(``),
|
||
_ = ref(!1),
|
||
v = 0,
|
||
y = 0,
|
||
b = 0;
|
||
(watch(
|
||
t,
|
||
() => {
|
||
(++v,
|
||
++y,
|
||
++b,
|
||
(i.value = null),
|
||
(s.value = null),
|
||
(l.value = !1),
|
||
(d.value = ``),
|
||
(o.value = ``),
|
||
(f.value = !1),
|
||
(h.value = !1),
|
||
(g.value = ``),
|
||
(_.value = !1));
|
||
},
|
||
{
|
||
flush: `sync`,
|
||
},
|
||
),
|
||
onScopeDispose(() => {
|
||
(++v, ++y, ++b);
|
||
}));
|
||
let x = computed(() => {
|
||
let e = M[t.value || `mf_cloud`] ?? M.mf_cloud;
|
||
return {
|
||
...e,
|
||
upgrade: e.upgrade && n.value?.upgrade_allowed !== !1,
|
||
};
|
||
}),
|
||
S = () => t.value;
|
||
// 镜像图标名经过 URL 编码后仅拼入本地固定图标目录。
|
||
function ee(e) {
|
||
return e
|
||
? `/plugins/server/mf_cloud/view/assets/default_icons/${encodeURIComponent(e)}.svg`
|
||
: ``;
|
||
}
|
||
// 把 mf_cloud/remf_cloud 详情转换为统一展示结构,同时保留 raw 供专用管理组件读取。
|
||
function te(e) {
|
||
let t = e.image ?? {},
|
||
n = String(t.icon ?? ``);
|
||
return {
|
||
module: S(),
|
||
ip: String(e.ip ?? ``),
|
||
ips: [String(e.ip ?? ``)].filter(Boolean),
|
||
powerStatus: String(e.power_status ?? ``),
|
||
image: {
|
||
name: String(t.name ?? ``),
|
||
icon: n,
|
||
iconUrl: String(t.icon_url ?? ``) || ee(n),
|
||
},
|
||
username: String(e.username ?? ``),
|
||
port: instance_data_c(e.port),
|
||
password: String(e.password ?? ``),
|
||
cpu: Number(e.cpu ?? 0),
|
||
memory: Number(e.memory ?? 0),
|
||
disks: [],
|
||
bw: Number(e.bw ?? 0),
|
||
protect: Number(e.peak_defence ?? 0),
|
||
lineName: String(e.line?.name ?? ``),
|
||
billMethodName: ``,
|
||
trafficText: Number(e.flow) > 0 ? `${e.flow} GB` : `不限量`,
|
||
securityGroupId: 0,
|
||
securityGroupName: ``,
|
||
raw: e,
|
||
};
|
||
}
|
||
// 从财务模块 host_data 与配置项提取实例规格;IP 去重,连接端口交给公共解析器处理。
|
||
function C(e) {
|
||
let t = instance_data_l(e.host_data),
|
||
n = instance_data_i(e.config_options),
|
||
r = (e) => n.find((t) => Number(t.option_type ?? 0) === e && t.sub_name),
|
||
i = (e) => {
|
||
let t = /(\d+(?:\.\d+)?)/.exec(String(e ?? ``));
|
||
return t ? Number(t[1]) : 0;
|
||
},
|
||
a = r(12),
|
||
o = r(5),
|
||
s = String(t.dedicatedip ?? ``),
|
||
c = Array.isArray(t.assignedips)
|
||
? t.assignedips.map(String)
|
||
: String(t.assignedips ?? ``).split(/[\s,]+/),
|
||
l = [...new Set([s, ...c].filter(Boolean))];
|
||
return {
|
||
module: S(),
|
||
ip: s,
|
||
ips: l,
|
||
powerStatus: ``,
|
||
image: {
|
||
name: String(o?.sub_name ?? String(t.os ?? ``)),
|
||
icon: ``,
|
||
iconUrl: ``,
|
||
},
|
||
username: String(t.username ?? ``),
|
||
port: instance_data_c(t.port),
|
||
password: String(t.password ?? ``),
|
||
cpu: i(r(6)?.sub_name),
|
||
memory: i(r(8)?.sub_name),
|
||
disks: [],
|
||
bw: i(r(18)?.sub_name) || i(r(10)?.sub_name),
|
||
protect: 0,
|
||
lineName: String(a?.sub_name ?? ``),
|
||
billMethodName: ``,
|
||
trafficText: ``,
|
||
securityGroupId: 0,
|
||
securityGroupName: ``,
|
||
raw: e,
|
||
};
|
||
}
|
||
// 整理弹性云的镜像、带宽计费和安全组字段,不改变原始接口数据。
|
||
function ne(e) {
|
||
let t = instance_data_a(e),
|
||
n = String(t.icon ?? ``);
|
||
return (
|
||
e.system_disk,
|
||
{
|
||
module: S(),
|
||
ip: String(e.ip ?? ``),
|
||
ips: Array.isArray(e.ips) ? e.ips : [String(e.ip ?? ``)],
|
||
powerStatus: String(e.power_status ?? ``),
|
||
image: {
|
||
name: t.name,
|
||
icon: n,
|
||
iconUrl: t.url || ee(n),
|
||
},
|
||
username: String(e.username ?? ``),
|
||
port: instance_data_c(e.port),
|
||
password: String(e.password ?? ``),
|
||
cpu: Number(e.cpu ?? 0),
|
||
memory: Number(e.memory ?? 0),
|
||
disks: [],
|
||
bw: Number(e.bandwidth ?? 0),
|
||
protect: Number(e.protect ?? 0),
|
||
lineName: String(e.line_name ?? ``),
|
||
billMethodName: String(e.bill_method_name ?? ``),
|
||
trafficText: Number(e.bill_method) === 2 ? `按流量计费` : `按带宽计费`,
|
||
securityGroupId: Number(e.security_group_id ?? 0),
|
||
securityGroupName: String(e.security_group_name ?? ``),
|
||
raw: e,
|
||
}
|
||
);
|
||
}
|
||
// 整理 jy 系列的多种字段来源;仅选有效数值作为统一规格,保留原始详情。
|
||
function w(e) {
|
||
let t = instance_data_l(e.host_data),
|
||
n = instance_data_a(e),
|
||
r = n.icon,
|
||
i = Array.isArray(e.ips) ? e.ips.map(String) : [],
|
||
a = Array.isArray(t.assignedips)
|
||
? t.assignedips.map(String)
|
||
: String(t.assignedips ?? ``).split(/[\s,]+/),
|
||
o = String(e.ip ?? e.public_ip ?? e.dedicatedip ?? t.dedicatedip ?? ``),
|
||
s = instance_data_l(e.line),
|
||
c = instance_data_i(e.config_options ?? e.configoptions),
|
||
l = (e) => c.find((t) => Number(t.option_type) === e),
|
||
u = (...e) => {
|
||
for (let t of e) {
|
||
if (t == null || String(t).trim() === ``) continue;
|
||
let e = Number(t);
|
||
if (Number.isFinite(e)) return e;
|
||
}
|
||
return 0;
|
||
},
|
||
d = String(n.name || e.os_name || t.os || l(5)?.sub_name || ``),
|
||
f = e.flow ?? e.traffic_total ?? e.total_traffic;
|
||
return {
|
||
module: S(),
|
||
ip: o,
|
||
ips: [...new Set([o, ...i, ...a].filter(Boolean))],
|
||
powerStatus: String(e.power_status ?? e.status ?? ``),
|
||
image: {
|
||
name: d,
|
||
icon: r,
|
||
iconUrl: n.url || ee(r),
|
||
},
|
||
username: String(e.username ?? t.username ?? ``),
|
||
port: instance_data_c(e.port ?? t.port),
|
||
password: String(e.password ?? t.password ?? ``),
|
||
cpu: u(e.cpu, e.cpu_num, e.cores, l(6)?.sub_name),
|
||
memory: u(e.memory, e.mem, e.memory_size, l(8)?.sub_name),
|
||
disks: [],
|
||
bw: u(e.bw, e.bandwidth, e.bandwidth_limit),
|
||
protect: u(e.defence, e.peak_defence, e.protect),
|
||
lineName: String(s.name ?? e.line_name ?? l(13)?.sub_name ?? ``),
|
||
billMethodName: String(e.bill_method_name ?? ``),
|
||
trafficText: f == null ? `` : String(f),
|
||
securityGroupId: 0,
|
||
securityGroupName: ``,
|
||
raw: e,
|
||
};
|
||
}
|
||
// 按模块读取并规范化磁盘列表;财务模块从快照/备份信息提取,明确空数组才作为无磁盘。
|
||
async function ie(t) {
|
||
if (t === `remf_finance`) {
|
||
let t = !1,
|
||
n;
|
||
for (let i of [`snapshot`, `backup`])
|
||
try {
|
||
let n = await r.get(`/remf_finance/${e}/${i}`),
|
||
a = instance_data_l(n),
|
||
o = a.disk ?? a.disks ?? a.disk_list;
|
||
if (typeof o == `string`)
|
||
try {
|
||
o = JSON.parse(o);
|
||
} catch {
|
||
o = null;
|
||
}
|
||
let s = instance_data_t(n);
|
||
if (s.length) return s;
|
||
Array.isArray(o) && o.length === 0 && (t = !0);
|
||
} catch (e) {
|
||
n ??= e;
|
||
}
|
||
if (t) return [];
|
||
throw n ?? Error(`暂未返回磁盘信息,请稍后重试`);
|
||
}
|
||
if (t === `mf_cloud` || t === `remf_cloud`)
|
||
return ((await r.get(`/${t}/${e}/disk`)).list ?? []).map((e) => ({
|
||
ident: String(e.id),
|
||
name: e.name,
|
||
size: e.size,
|
||
type: e.type || `—`,
|
||
type2: e.type2 === `system` ? `system` : `data`,
|
||
status: Number(e.status ?? 0),
|
||
createTime: e.create_time,
|
||
raw: e,
|
||
}));
|
||
if (t === `jy_cloud` || t === `jy_dcim`) {
|
||
let n = await r.get(`/${t}/${e}/disk`),
|
||
i = instance_data_l(n);
|
||
return instance_data_i(
|
||
Array.isArray(n) ? n : (i.list ?? i.disk ?? i.disks ?? i.disk_list),
|
||
).map((e, t) => {
|
||
let n = String(
|
||
e.type2 ?? e.type ?? e.disk_property ?? e.disk_type ?? ``,
|
||
).toLowerCase(),
|
||
r =
|
||
[`system`, `sys`, `1`].includes(n) ||
|
||
/系统/.test(String(e.name ?? e.disk_name ?? ``));
|
||
return {
|
||
ident: String(e.id ?? e.disk_id ?? e.disk_identity ?? t),
|
||
name: String(
|
||
e.name ??
|
||
e.disk_name ??
|
||
e.disk_property_txt ??
|
||
(r ? `系统盘` : `数据盘`),
|
||
),
|
||
size: Number(e.size ?? e.disk_size ?? 0),
|
||
type: String(
|
||
e.fs_type ?? e.type_name ?? e.disk_type ?? e.type ?? `—`,
|
||
),
|
||
type2: r ? `system` : `data`,
|
||
status: Number(e.status ?? e.disk_status ?? -1),
|
||
createTime: instance_data_u(e.create_time ?? e.created_at),
|
||
raw: e,
|
||
};
|
||
});
|
||
}
|
||
return ((await r.get(`/kky_ecs/disk/${e}`)).list ?? []).map((e) => ({
|
||
ident: String(e.disk_identity ?? ``),
|
||
name: String(e.disk_property_txt ?? `磁盘`),
|
||
size: Number(e.disk_size ?? 0),
|
||
type: String(e.disk_type ?? `—`),
|
||
type2: Number(e.disk_property) === 1 ? `system` : `data`,
|
||
status: Number(e.disk_status ?? 0),
|
||
createTime: e.created_at
|
||
? Math.floor(
|
||
new Date(String(e.created_at).replace(/-/g, `/`)).getTime() / 1e3,
|
||
)
|
||
: void 0,
|
||
raw: e,
|
||
}));
|
||
}
|
||
// 磁盘异步结果同时绑定模块、详情代次和磁盘请求代次,失败只更新磁盘区域。
|
||
async function ae() {
|
||
let e = t.value;
|
||
if (!e || !i.value || M[e].disk === !1) return;
|
||
let n = ++y,
|
||
r = v,
|
||
a = () => n === y && r === v && e === t.value;
|
||
((h.value = !0), (g.value = ``));
|
||
try {
|
||
let t = await ie(e);
|
||
if (!a() || !i.value) return;
|
||
((i.value.disks = t), (_.value = !0));
|
||
} catch (e) {
|
||
a() && (g.value = e instanceof Error ? e.message : `加载磁盘信息失败`);
|
||
} finally {
|
||
a() && (h.value = !1);
|
||
}
|
||
}
|
||
// 状态查询有独立 12 秒截止时间;结果缺少有效 rescue 标记时保留详情已有标记,不用未知状态冒充关机。
|
||
async function T() {
|
||
let n = S();
|
||
if (!n) return;
|
||
let a = ++b,
|
||
c = v;
|
||
l.value = !0;
|
||
let u = () => a === b && c === v && t.value === n;
|
||
try {
|
||
let t = await r.get(`/${n}/${e}/status`, void 0, !1, {
|
||
timeoutMs: 12e3,
|
||
});
|
||
if (!u()) return;
|
||
let a = s.value ?? {},
|
||
c = {
|
||
...a,
|
||
...t,
|
||
},
|
||
l = (e) =>
|
||
typeof e == `boolean` || [`0`, `1`].includes(String(e ?? ``));
|
||
(!l(t?.rescue) && l(a.rescue) && (c.rescue = a.rescue), (s.value = c));
|
||
let f = typeof t?.status == `string` ? t.status : ``;
|
||
((d.value = f ? `` : `状态暂不可用`),
|
||
(o.value = String(t?.desc ?? ``)),
|
||
i.value &&
|
||
t?.status !== void 0 &&
|
||
t.status !== null &&
|
||
(i.value.powerStatus = String(t.status)));
|
||
} catch {
|
||
u() && ((o.value = ``), (d.value = `状态暂不可用`));
|
||
} finally {
|
||
u() && (l.value = !1);
|
||
}
|
||
}
|
||
// 并行发起状态与详情查询,按模块归一化详情后再加载磁盘;缺失连接端口时单独读取 remote_info。
|
||
async function oe(n) {
|
||
let a = t.value;
|
||
if (!a) return;
|
||
let o = ++v;
|
||
(++y, ++b, (h.value = !1));
|
||
let c = () => o === v && a === t.value;
|
||
((f.value = !0), (m.value = ``));
|
||
try {
|
||
let t = n?.initial ?? r.get(`/${a}/${e}`);
|
||
T();
|
||
let o = await t;
|
||
if (!c()) return;
|
||
let l =
|
||
a === `mf_cloud` ||
|
||
a === `remf_cloud` ||
|
||
a === `jy_cloud` ||
|
||
a === `jy_dcim`
|
||
? a === `jy_cloud` || a === `jy_dcim`
|
||
? w(o)
|
||
: te(o)
|
||
: a === `remf_finance`
|
||
? C(o)
|
||
: ne(o);
|
||
l.disks = i.value?.module === a ? i.value.disks : [];
|
||
let u = s.value;
|
||
((l.powerStatus = String(u?.status ?? l.powerStatus)),
|
||
(i.value = l),
|
||
(a === `mf_cloud` || a === `remf_cloud`) &&
|
||
l.port === null &&
|
||
r
|
||
.get(`/${a}/${e}/remote_info`, void 0, !1, {
|
||
timeoutMs: 12e3,
|
||
})
|
||
.then((e) => {
|
||
c() && i.value && (i.value.port = instance_data_c(e.port));
|
||
})
|
||
.catch(() => {}),
|
||
ae());
|
||
} catch (e) {
|
||
c() && (m.value = e instanceof Error ? e.message : `加载实例信息失败`);
|
||
} finally {
|
||
c() && (f.value = !1);
|
||
}
|
||
}
|
||
// 先核对模块电源能力及强制操作能力,再携带可选操作密码请求,完成后重新读取状态。
|
||
async function se(t, n = ``) {
|
||
if (!M[S()]?.power) throw Error(`当前模块暂未开放电源管理操作`);
|
||
if (t.startsWith(`hard_`) && !M[S()]?.hardPower)
|
||
throw Error(`当前模块暂未开放强制电源操作`);
|
||
let i = n
|
||
? {
|
||
client_operate_password: n,
|
||
}
|
||
: void 0;
|
||
(await r.post(`/${S()}/${e}/${t}`, i), await T());
|
||
}
|
||
// 密码重置按模块组装既有字段契约,不能把 kky 与其他模块的参数形状直接互换。
|
||
async function ce(t, n = ``, i = ``) {
|
||
if (!M[S()]?.passwordReset) throw Error(`当前模块暂未开放密码重置操作`);
|
||
S() === `kky_ecs`
|
||
? await r.post(`/kky_ecs/${e}/reset_password`, {
|
||
password: t,
|
||
client_operate_password: n,
|
||
})
|
||
: await r.post(`/${S()}/${e}/reset_password`, {
|
||
id: e,
|
||
password: t,
|
||
code: i,
|
||
client_operate_password: n,
|
||
client_operate_methods: `rePassSub`,
|
||
remember_operate_password: 0,
|
||
});
|
||
}
|
||
return {
|
||
info: i,
|
||
powerDesc: o,
|
||
statusData: s,
|
||
statusLoading: l,
|
||
statusError: d,
|
||
loading: f,
|
||
error: m,
|
||
disksLoading: h,
|
||
disksError: g,
|
||
disksLoaded: _,
|
||
caps: x,
|
||
load: oe,
|
||
refreshDisks: ae,
|
||
loadStatus: T,
|
||
power: se,
|
||
resetPassword: ce,
|
||
module: t,
|
||
hostId: e,
|
||
};
|
||
}
|
||
var N = new Set([
|
||
`remf_cloud`,
|
||
`remf_finance_dcim`,
|
||
`remf_finance_common`,
|
||
`idcsmart_common`,
|
||
`reidcsmart_common`,
|
||
]),
|
||
De = [`on`, `off`, `reboot`],
|
||
P = (e) => (e && typeof e == `object` && !Array.isArray(e) ? e : null),
|
||
F = (e) => e === `idcsmart_common` || e === `reidcsmart_common`,
|
||
I = (e) => e === !0 || e === 1 || e === `1` || e === `on` || e === `true`,
|
||
L = (e) => e === !1 || e === 0 || e === `0` || e === `off` || e === `false`;
|
||
// 从后端按钮元数据提取允许与禁止电源动作;显式禁用优先于允许,同名动作不能被另一条配置重新放开。
|
||
function R(e) {
|
||
let t = new Set(),
|
||
n = new Set(),
|
||
r = Array.isArray(e) ? e : [e];
|
||
for (let e of r) {
|
||
let r = P(e);
|
||
if (!r) continue;
|
||
let i =
|
||
`func` in r
|
||
? [r]
|
||
: [r.console, r.control].flatMap((e) => (Array.isArray(e) ? e : []));
|
||
for (let e of i) {
|
||
let r = P(e),
|
||
i = r?.func;
|
||
!r ||
|
||
!De.includes(i) ||
|
||
(r.type && r.type !== "default") ||
|
||
(I(r.disabled) || L(r.enabled) || L(r.enable) ? n.add(i) : t.add(i));
|
||
}
|
||
}
|
||
for (let e of n) t.delete(e);
|
||
return {
|
||
allowed: t,
|
||
blocked: n,
|
||
};
|
||
}
|
||
var z = (e) => R(e).allowed;
|
||
// 按旧模块的实际权限形状计算动作集合,兼顾 dcim 授权与手工资源控制模式;未知模块不开放电源操作。
|
||
function Oe(e, t) {
|
||
if (F(e)) return z(t.client_button);
|
||
if (e === `remf_finance_common`) return z(t.module_button);
|
||
if (e === `remf_finance_dcim`) {
|
||
let e = P(t.dcim)?.auth,
|
||
n = P(e),
|
||
r = R(t.module_button);
|
||
return new Set(
|
||
De.filter((t) =>
|
||
L(e) || (n && L(n[t])) || r.blocked.has(t)
|
||
? !1
|
||
: I(e) || !!(n && I(n[t])) || r.allowed.has(t),
|
||
),
|
||
);
|
||
}
|
||
if (e === `remf_cloud`) {
|
||
let e = P(t.config);
|
||
return Number(e?.manual_resource) === 1 &&
|
||
(!e?.manual_resource_control_mode ||
|
||
e.manual_resource_control_mode === `not_support`)
|
||
? new Set()
|
||
: `module_button` in t
|
||
? z(t.module_button)
|
||
: new Set(De);
|
||
}
|
||
return new Set();
|
||
}
|
||
// 旧/通用实例电源权限与状态控制器:权限元数据必须属于当前模块才能开放动作,提交期间互斥。
|
||
function ke(e, t) {
|
||
let n = useApi(),
|
||
r = ref(!1),
|
||
i = ref(``),
|
||
o = ref(null),
|
||
s = ref(``),
|
||
l = ref(!1),
|
||
d = ref(``),
|
||
f = 0,
|
||
p = ref(new Set()),
|
||
m = ``,
|
||
h = 0,
|
||
g = !1,
|
||
_ = !1;
|
||
// 模块重载、切换或销毁时清空权限和状态,并让已有异步结果失效。
|
||
function v() {
|
||
(h++,
|
||
f++,
|
||
(s.value = ``),
|
||
(d.value = ``),
|
||
(l.value = !1),
|
||
(m = ``),
|
||
(o.value = null),
|
||
(p.value = new Set()),
|
||
(i.value = ``),
|
||
(r.value = !1));
|
||
}
|
||
// 只有当前模块元数据已成功加载、没有错误且动作被允许时才可提交。
|
||
function y(e) {
|
||
return !g && !r.value && !i.value && m === t.value && p.value.has(e);
|
||
}
|
||
// 刷新旧模块电源状态;状态错误独立于权限错误,不把查询失败转为已关机。
|
||
async function b() {
|
||
let r = t.value;
|
||
if (g || m !== r || !N.has(r)) return;
|
||
let i = ++f,
|
||
a = h,
|
||
o = () => !g && i === f && a === h && t.value === r;
|
||
l.value = !0;
|
||
try {
|
||
let t = await instance_status_r(n, r, e);
|
||
if (!o()) return;
|
||
((s.value = t), (d.value = t ? `` : `状态暂不可用`));
|
||
} catch {
|
||
o() && ((s.value = ``), (d.value = `状态暂不可用`));
|
||
} finally {
|
||
o() && (l.value = !1);
|
||
}
|
||
}
|
||
// 先重置旧权限,再读取当前模块配置;已有初始详情可复用,空响应不授予任何操作。
|
||
async function x(a) {
|
||
v();
|
||
let s = t.value;
|
||
if (g || !N.has(s) || !/^[1-9]\d*$/.test(e)) return;
|
||
let c = h,
|
||
l = () => !g && c === h && t.value === s;
|
||
r.value = !0;
|
||
try {
|
||
let t = F(s) ? `/${s}/host/${e}/configoption` : `/${s}/${e}`,
|
||
r = a && `initial` in a ? a.initial : await n.get(t);
|
||
if (!l()) return;
|
||
let i = P(r);
|
||
if (!i || !Object.keys(i).length) throw Error(`实例电源权限信息无效`);
|
||
((o.value = i), (p.value = Oe(s, i)), (m = s), b());
|
||
} catch (e) {
|
||
l() &&
|
||
(i.value = e instanceof Error ? e.message : `实例电源权限加载失败`);
|
||
} finally {
|
||
l() && (r.value = !1);
|
||
}
|
||
}
|
||
// 请求前再次检查当前权限与互斥标记,响应后复查模块/代次;切换实例后要求核实操作结果。
|
||
async function S(r, i = ``) {
|
||
if (!y(r)) throw Error(`当前实例不支持此电源操作或权限尚未加载`);
|
||
if (_) throw Error(`电源操作正在提交,请稍候`);
|
||
let a = t.value,
|
||
o = h,
|
||
s = F(a) ? `/${a}/host/${e}/provision/${r}` : `/${a}/${e}/${r}`,
|
||
c = i
|
||
? {
|
||
client_operate_password: i,
|
||
}
|
||
: {};
|
||
_ = !0;
|
||
try {
|
||
if ((await n.post(s, c), g || o !== h || t.value !== a))
|
||
throw Error(`实例已切换,请重新确认操作结果`);
|
||
} finally {
|
||
_ = !1;
|
||
}
|
||
}
|
||
return (
|
||
watch(t, v, {
|
||
flush: `sync`,
|
||
}),
|
||
onScopeDispose(() => {
|
||
((g = !0), v());
|
||
}),
|
||
{
|
||
loading: r,
|
||
error: i,
|
||
metadata: o,
|
||
powerStatus: s,
|
||
statusLoading: l,
|
||
statusError: d,
|
||
loadStatus: b,
|
||
can: y,
|
||
load: x,
|
||
power: S,
|
||
reset: v,
|
||
}
|
||
);
|
||
}
|
||
var Ae = publicAssetsURL(`/images/reference/cloud-server.png`),
|
||
je = defineAsyncComponent(() =>
|
||
loadModule(
|
||
() =>
|
||
import("~/components/instance/InstanceManage.vue").then(
|
||
(e) => e.default || e,
|
||
),
|
||
[],
|
||
import.meta.url,
|
||
),
|
||
),
|
||
Me = defineAsyncComponent(() =>
|
||
loadModule(
|
||
() =>
|
||
import("~/components/instance/DcimManage.vue").then(
|
||
(e) => e.default || e,
|
||
),
|
||
[],
|
||
import.meta.url,
|
||
),
|
||
),
|
||
Ne = defineAsyncComponent(() =>
|
||
loadModule(
|
||
() =>
|
||
import("~/components/instance/LegacyDcimManage.vue").then(
|
||
(e) => e.default || e,
|
||
),
|
||
[],
|
||
import.meta.url,
|
||
),
|
||
),
|
||
Pe = defineAsyncComponent(() =>
|
||
loadModule(
|
||
() =>
|
||
import("~/components/PaymentDialog.vue").then((e) => e.default || e),
|
||
[],
|
||
import.meta.url,
|
||
),
|
||
),
|
||
Fe = defineAsyncComponent(() =>
|
||
loadModule(
|
||
() =>
|
||
import("~/components/instance/InstanceRenewDialog.vue").then(
|
||
(e) => e.default || e,
|
||
),
|
||
[],
|
||
import.meta.url,
|
||
),
|
||
),
|
||
Ie = {
|
||
class: `page`,
|
||
},
|
||
Le = {
|
||
class: `host-panel`,
|
||
role: `status`,
|
||
"aria-label": `正在加载实例信息`,
|
||
"aria-busy": `true`,
|
||
},
|
||
Re = {
|
||
class: `host-head`,
|
||
"aria-hidden": `true`,
|
||
},
|
||
ze = {
|
||
class: `host-ident`,
|
||
},
|
||
Be = {
|
||
class: `host-avatar`,
|
||
},
|
||
Ve = {
|
||
class: `host-id host-id-skeleton`,
|
||
},
|
||
He = {
|
||
class: `host-title`,
|
||
},
|
||
Ue = {
|
||
class: `host-sub`,
|
||
},
|
||
We = {
|
||
class: `host-facts`,
|
||
},
|
||
Ge = {
|
||
class: `host-actions host-actions-skeleton`,
|
||
},
|
||
Ke = {
|
||
key: 1,
|
||
class: `panel load-error`,
|
||
},
|
||
qe = {
|
||
class: `host-panel`,
|
||
},
|
||
Je = {
|
||
class: `host-head`,
|
||
},
|
||
Ye = {
|
||
class: `host-ident`,
|
||
},
|
||
Xe = {
|
||
class: `host-avatar`,
|
||
},
|
||
Ze = [`aria-label`, `title`],
|
||
Qe = {
|
||
class: `host-id`,
|
||
},
|
||
$e = {
|
||
class: `host-title`,
|
||
},
|
||
et = {
|
||
class: `host-no`,
|
||
},
|
||
tt = [`aria-label`],
|
||
nt = {
|
||
class: `host-sub`,
|
||
},
|
||
rt = {
|
||
class: `host-name`,
|
||
},
|
||
it = {
|
||
class: `host-notes`,
|
||
},
|
||
at = {
|
||
class: `host-facts`,
|
||
},
|
||
ot = {
|
||
class: `fact`,
|
||
},
|
||
st = {
|
||
class: `fact`,
|
||
},
|
||
ct = {
|
||
key: 0,
|
||
role: `status`,
|
||
},
|
||
lt = {
|
||
key: 1,
|
||
class: `ip-error`,
|
||
},
|
||
ut = [`title`],
|
||
dt = {
|
||
key: 2,
|
||
class: `ip-value`,
|
||
},
|
||
ft = {
|
||
class: `mono`,
|
||
},
|
||
pt = [`aria-label`, `title`],
|
||
mt = {
|
||
class: `fact`,
|
||
},
|
||
ht = {
|
||
class: `fact`,
|
||
},
|
||
gt = {
|
||
key: 0,
|
||
class: `power-confirm-text`,
|
||
},
|
||
_t = {
|
||
key: 0,
|
||
class: `power-confirm-error`,
|
||
role: `alert`,
|
||
},
|
||
vt = _plugin_vue_export_helper_t(
|
||
defineComponent({
|
||
__name: `server`,
|
||
setup(s) {
|
||
let c = useRoute(),
|
||
b = useApi(),
|
||
C = String(c.query.id ?? ``);
|
||
composables_t({
|
||
key: (e) => e.fullPath,
|
||
});
|
||
let w = ref(null),
|
||
T = ref(!0),
|
||
E = ref(``),
|
||
D = ref(!1),
|
||
O = 0,
|
||
k = !1,
|
||
A = ref(null),
|
||
ye = ref(``),
|
||
j = ref(!1),
|
||
M = computed(() =>
|
||
[
|
||
`idcsmart_common`,
|
||
`reidcsmart_common`,
|
||
`remf_finance_common`,
|
||
].includes(G.value)
|
||
? G.value
|
||
: ``,
|
||
),
|
||
N = ref(null),
|
||
De = ref(!1),
|
||
P = ref(``),
|
||
F = 0,
|
||
I = ref(``),
|
||
L = ref(!1),
|
||
R = ref(!1),
|
||
z = ref(``),
|
||
Oe = ref(!1),
|
||
vt = ref(null),
|
||
yt = ref(``),
|
||
bt = ref(``),
|
||
B = ref(``),
|
||
V = computed(() => {
|
||
let e = B.value;
|
||
return e === `mf_cloud` ||
|
||
e === `remf_cloud` ||
|
||
e === `kky_ecs` ||
|
||
e === `jy_cloud` ||
|
||
e === `jy_dcim`
|
||
? e
|
||
: e === `mf_finance` || e === `remf_finance`
|
||
? `remf_finance`
|
||
: ``;
|
||
}),
|
||
H = Ee(C, V, w),
|
||
U = computed(() =>
|
||
B.value === `mf_dcim` || B.value === `remf_dcim` ? B.value : ``,
|
||
),
|
||
xt = ref(null),
|
||
W = ref(null),
|
||
G = computed(() => {
|
||
let e = B.value.replace(
|
||
/^mf_finance_(dcim|common)$/,
|
||
`remf_finance_$1`,
|
||
);
|
||
return [
|
||
`remf_cloud`,
|
||
`remf_finance_dcim`,
|
||
`remf_finance_common`,
|
||
`idcsmart_common`,
|
||
`reidcsmart_common`,
|
||
].includes(e) && !V.value
|
||
? e
|
||
: ``;
|
||
}),
|
||
K = ke(C, G),
|
||
St = computed(() =>
|
||
G.value === `remf_finance_dcim` ? `remf_finance_dcim` : ``,
|
||
),
|
||
Ct = computed(() => V.value || G.value),
|
||
wt = {
|
||
mf_cloud: {
|
||
to: `/cloud-servers`,
|
||
label: `返回云服务器列表`,
|
||
},
|
||
kky_ecs: {
|
||
to: `/cloud-servers`,
|
||
label: `返回云服务器列表`,
|
||
},
|
||
mf_dcim: {
|
||
to: `/dedicated-servers`,
|
||
label: `返回物理服务器列表`,
|
||
},
|
||
remf_dcim: {
|
||
to: `/dedicated-servers`,
|
||
label: `返回物理服务器列表`,
|
||
},
|
||
remf_cloud: {
|
||
to: `/cloud-servers`,
|
||
label: `返回云服务器列表`,
|
||
},
|
||
jy_cloud: {
|
||
to: `/cloud-servers`,
|
||
label: `返回云服务器列表`,
|
||
},
|
||
jy_dcim: {
|
||
to: `/dedicated-servers`,
|
||
label: `返回物理服务器列表`,
|
||
},
|
||
mf_finance_dcim: {
|
||
to: `/dedicated-servers`,
|
||
label: `返回物理服务器列表`,
|
||
},
|
||
remf_finance_dcim: {
|
||
to: `/dedicated-servers`,
|
||
label: `返回物理服务器列表`,
|
||
},
|
||
reidcsmart_common: {
|
||
to: `/`,
|
||
label: `返回首页`,
|
||
},
|
||
idcsmart_common: {
|
||
to: `/`,
|
||
label: `返回首页`,
|
||
},
|
||
},
|
||
Tt = computed(() => {
|
||
let e = Number(c.query.m);
|
||
if (
|
||
Number.isSafeInteger(e) &&
|
||
e > 0 &&
|
||
[`cloud-servers`, `dedicated-servers`].includes(
|
||
String(c.query.list),
|
||
)
|
||
) {
|
||
let t = c.query.list === `cloud-servers`;
|
||
return {
|
||
to: `/${t ? `cloud-servers` : `dedicated-servers`}?m=${e}`,
|
||
label: t ? `返回云服务器列表` : `返回物理服务器列表`,
|
||
};
|
||
}
|
||
return V.value === `remf_finance`
|
||
? {
|
||
to: `/cloud-servers`,
|
||
label: `返回云服务器列表`,
|
||
}
|
||
: server_page_n({
|
||
product_id: Number(bt.value),
|
||
module: B.value,
|
||
})
|
||
? {
|
||
to: `/dedicated-servers`,
|
||
label: `返回物理服务器列表`,
|
||
}
|
||
: (wt[B.value] ?? {
|
||
to: `/cloud-servers`,
|
||
label: `返回产品列表`,
|
||
});
|
||
});
|
||
// 非统一云详情模块独立读取主机 IP,使用请求序号避免旧响应覆盖。
|
||
async function Et() {
|
||
if (V.value) return;
|
||
let e = ++F;
|
||
((De.value = !0), (P.value = ``));
|
||
try {
|
||
let t = await b.get(`/host/${C}/ip`);
|
||
e === F && (N.value = t);
|
||
} catch (t) {
|
||
e === F &&
|
||
(P.value = t instanceof Error ? t.message : `IP 地址加载失败`);
|
||
} finally {
|
||
e === F && (De.value = !1);
|
||
}
|
||
}
|
||
// 读取通用主机配置并把同一份响应交给权限控制器,避免两次查询得到不同权限快照。
|
||
async function Dt(e = O) {
|
||
let t = () => !k && e === O;
|
||
K.reset();
|
||
try {
|
||
let e =
|
||
B.value === `reidcsmart_common`
|
||
? `reidcsmart_common`
|
||
: `idcsmart_common`,
|
||
n = await b.get(`/${e}/host/${C}/configoption`);
|
||
t() &&
|
||
((A.value = n),
|
||
await K.load({
|
||
initial: n,
|
||
}));
|
||
} catch (e) {
|
||
t() &&
|
||
(ye.value = e instanceof Error ? e.message : `主机配置加载失败`);
|
||
}
|
||
}
|
||
// 主机或商品不匹配时清空所有展示与模块信息,废弃旧 IP 请求,防止混合显示不同实例。
|
||
function Ot() {
|
||
((w.value = null),
|
||
(B.value = ``),
|
||
(bt.value = ``),
|
||
(I.value = ``),
|
||
(ye.value = ``),
|
||
(A.value = null),
|
||
(W.value = null),
|
||
(F += 1),
|
||
(N.value = null),
|
||
(P.value = ``),
|
||
(De.value = !1));
|
||
}
|
||
// 先严格核对 /host 响应 ID 与商品,再补取实际模块;按模块组合加载详情、IP、配置和电源权限。
|
||
async function q() {
|
||
if (k) return;
|
||
let e = ++O,
|
||
t = () => !k && e === O && String(c.query.id ?? ``) === C;
|
||
(String(w.value?.id ?? ``) !== C && Ot(),
|
||
(T.value = !w.value),
|
||
(D.value = !0),
|
||
(E.value = ``),
|
||
(ye.value = ``));
|
||
let n = !1;
|
||
try {
|
||
if (!C) throw Error(`缺少实例 ID,请从实例列表重新进入`);
|
||
let r = await b.get(`/host/${C}`);
|
||
if (!t()) return;
|
||
let i = r?.host,
|
||
a = i && typeof i == `object` ? i.id : void 0,
|
||
o = i && typeof i == `object` ? i.product_id : void 0;
|
||
if (
|
||
!i ||
|
||
typeof i != `object` ||
|
||
Array.isArray(i) ||
|
||
a == null ||
|
||
String(a) !== C ||
|
||
o == null
|
||
)
|
||
throw Error(`实例信息无效或已不存在,请重试`);
|
||
let s = String(bt.value) === String(o),
|
||
c = s ? B.value : ``;
|
||
(w.value && !s && Ot(),
|
||
(w.value = i),
|
||
(n = !0),
|
||
(I.value = i.notes || ``),
|
||
(bt.value = o),
|
||
(T.value = !1));
|
||
let l = i.module || c;
|
||
if (!l)
|
||
try {
|
||
l = (await b.get(`/product/${o}`)).product?.module ?? ``;
|
||
} catch {}
|
||
if (!t()) return;
|
||
if (!l || [`mf_cloud`, `mf_dcim`, `idcsmart_common`].includes(l)) {
|
||
let e = await b.get(`/host/${C}/view`);
|
||
if (!t()) return;
|
||
if (!e?.module) throw Error(`管理接口信息加载失败,请重试`);
|
||
l = e.module;
|
||
}
|
||
if (!t()) return;
|
||
((B.value = l),
|
||
l === `mf_cloud` ||
|
||
l === `remf_cloud` ||
|
||
l === `kky_ecs` ||
|
||
l === `jy_cloud` ||
|
||
l === `jy_dcim` ||
|
||
l === `mf_finance` ||
|
||
l === `remf_finance`
|
||
? await H.load()
|
||
: l === `idcsmart_common` || l === `reidcsmart_common`
|
||
? await Promise.all([Et(), Dt(e)])
|
||
: [
|
||
`remf_cloud`,
|
||
`mf_finance_dcim`,
|
||
`remf_finance_dcim`,
|
||
`mf_finance_common`,
|
||
`remf_finance_common`,
|
||
].includes(l)
|
||
? await Promise.all([Et(), K.load()])
|
||
: await Et());
|
||
} catch (e) {
|
||
t() &&
|
||
(n ? (B.value = ``) : Ot(),
|
||
(E.value = e instanceof Error ? e.message : `加载失败`));
|
||
} finally {
|
||
t() && ((T.value = !1), (D.value = !1));
|
||
}
|
||
}
|
||
// 保存备注时绑定主机对象与加载代次;离页/切换后不把旧备注回填到新实例。
|
||
async function kt() {
|
||
let e = w.value;
|
||
if (R.value || !e || k) return;
|
||
let t = O,
|
||
n = I.value,
|
||
r = () =>
|
||
!k && t === O && w.value === e && String(c.query.id ?? ``) === C;
|
||
((R.value = !0), (z.value = ``));
|
||
try {
|
||
if (
|
||
(await b.put(`/host/${C}/notes`, {
|
||
id: C,
|
||
notes: n,
|
||
}),
|
||
!r())
|
||
)
|
||
return;
|
||
((e.notes = n), (L.value = !1));
|
||
} catch (e) {
|
||
r() && (z.value = e instanceof Error ? e.message : `保存备注失败`);
|
||
} finally {
|
||
R.value = !1;
|
||
}
|
||
}
|
||
// 打开备注编辑时从最新主机对象复制草稿,提交中不重新打开。
|
||
function At() {
|
||
w.value &&
|
||
!R.value &&
|
||
((z.value = ``), (I.value = w.value.notes || ``), (L.value = !0));
|
||
}
|
||
// 为当前实例尚未完成的原订单打开支付,使用已有订单而非再次创建。
|
||
function jt() {
|
||
w.value?.order_id &&
|
||
((vt.value = w.value.order_id),
|
||
(yt.value = String(w.value.first_payment_amount ?? ``)),
|
||
(Oe.value = !0));
|
||
}
|
||
// 续费/升级等子组件返回订单后统一打开支付弹窗。
|
||
function Mt(e) {
|
||
((vt.value = e.order_id),
|
||
(yt.value = String(e.amount ?? ``)),
|
||
(Oe.value = !0));
|
||
}
|
||
let Nt = ref(0);
|
||
// 操作完成后重载实例并递增刷新键,让需要重新挂载的管理区域同步更新。
|
||
async function Pt() {
|
||
(await q(), k || Nt.value++);
|
||
}
|
||
let J = ref(``);
|
||
// 复制非空字段并短暂标识具体复制项,不在日志中输出连接资料。
|
||
async function Ft(e, t) {
|
||
if (e)
|
||
try {
|
||
(await navigator.clipboard.writeText(e),
|
||
(J.value = t),
|
||
setTimeout(() => (J.value = ``), 1500));
|
||
} catch {}
|
||
}
|
||
let It = computed(
|
||
() =>
|
||
W.value?.region ||
|
||
configuration_display_n(
|
||
V.value || w.value?.module || ``,
|
||
H.info.value?.raw ?? A.value,
|
||
w.value,
|
||
).region ||
|
||
`—`,
|
||
),
|
||
Lt = computed(() => {
|
||
if (W.value?.spec) return W.value.spec;
|
||
let e = H.info.value;
|
||
if (!e) return w.value?.base_info || `—`;
|
||
let t = [
|
||
e.cpu
|
||
? V.value === `jy_dcim`
|
||
? `${e.cpu} 颗 CPU`
|
||
: `${e.cpu}vCPU`
|
||
: ``,
|
||
e.memory ? `${e.memory}GB` : ``,
|
||
].filter(Boolean);
|
||
return t.length ? t.join(` | `) : w.value?.base_info || `—`;
|
||
}),
|
||
Rt = computed(() =>
|
||
W.value?.ip
|
||
? W.value.ip
|
||
: !V.value && N.value
|
||
? N.value.dedicate_ip || N.value.assign_ip || `暂无 IP`
|
||
: H.info.value?.ip ||
|
||
String(w.value?.ip || w.value?.dedicate_ip || `—`),
|
||
),
|
||
zt = computed(() => Rt.value !== `—` && Rt.value !== `暂无 IP`),
|
||
Y = ref(``),
|
||
Bt = computed(() => {
|
||
let e = ``,
|
||
t = D.value;
|
||
return (
|
||
E.value ||
|
||
(V.value
|
||
? ((e = H.statusError.value
|
||
? ``
|
||
: H.info.value?.powerStatus || ``),
|
||
(t ||= H.statusLoading.value))
|
||
: U.value
|
||
? (e = W.value?.power || ``)
|
||
: G.value &&
|
||
((e = K.statusError.value ? `` : K.powerStatus.value),
|
||
(t ||= K.statusLoading.value))),
|
||
instance_status_t(Y.value ? `operating` : e, w.value?.status, t)
|
||
);
|
||
}),
|
||
Vt;
|
||
// 仅在页面可见、实例 Active、无弹窗且无其他动作时刷新电源状态,避免状态查询与操作冲突。
|
||
function Ht() {
|
||
k ||
|
||
D.value ||
|
||
Y.value ||
|
||
E.value ||
|
||
w.value?.status !== `Active` ||
|
||
document.querySelector(`.p-dialog-mask`) ||
|
||
(V.value && !H.statusLoading.value
|
||
? H.loadStatus()
|
||
: U.value
|
||
? xt.value?.refreshStatus()
|
||
: G.value && !K.statusLoading.value && K.loadStatus());
|
||
}
|
||
let X = ref(null),
|
||
Z = ref(``),
|
||
Ut = ref(``),
|
||
Wt = 0,
|
||
Gt = !1,
|
||
Kt = ref(``),
|
||
qt = ref(``);
|
||
// 成功反馈清除之前的错误;仅提示指令已下发,不保证实例已经进入最终电源状态。
|
||
function Jt(e) {
|
||
((qt.value = ``),
|
||
(Kt.value = e),
|
||
setTimeout(() => (Kt.value = ``), 4e3));
|
||
}
|
||
// 统一提取操作异常消息,失败与成功提示互斥。
|
||
function Yt(e, t) {
|
||
((Kt.value = ``), (qt.value = e instanceof Error ? e.message : t));
|
||
}
|
||
// 识别后端 operate_password 标记,决定是否保留确认框要求再次输入操作密码。
|
||
function Xt(e) {
|
||
if (!e || typeof e != `object`) return !1;
|
||
let t = e.data;
|
||
return !!t && typeof t == `object` && t.operate_password === 1;
|
||
}
|
||
// 确认电源动作快照仍匹配当前路由、主机、模块、状态和权限,防止确认期间切换目标。
|
||
function Zt(e) {
|
||
return (
|
||
!Gt &&
|
||
String(c.query.id ?? ``) === e.hostId &&
|
||
C === e.hostId &&
|
||
String(w.value?.id ?? ``) === e.hostId &&
|
||
Ct.value === e.module &&
|
||
w.value?.status === `Active` &&
|
||
!E.value &&
|
||
!ye.value &&
|
||
(!G.value || K.can(e.action))
|
||
);
|
||
}
|
||
// 按云/物理/旧模块分流电源动作;创建确认快照时冻结目标实例与动作,最终提交仍再校验。
|
||
function Q(e) {
|
||
if (U.value) {
|
||
!T.value &&
|
||
!D.value &&
|
||
w.value?.status === `Active` &&
|
||
xt.value?.requestAction(e);
|
||
return;
|
||
}
|
||
if (
|
||
Gt ||
|
||
(!G.value && !H.caps.value.power) ||
|
||
Y.value ||
|
||
j.value ||
|
||
T.value ||
|
||
D.value ||
|
||
!w.value ||
|
||
!Ct.value
|
||
)
|
||
return;
|
||
let t = {
|
||
action: e,
|
||
label: {
|
||
on: `开机`,
|
||
off: `关机`,
|
||
reboot: `重启`,
|
||
}[e],
|
||
hostId: C,
|
||
hostName:
|
||
w.value.name ||
|
||
product_name_n(w.value.product_name) ||
|
||
`实例 #${C}`,
|
||
module: Ct.value,
|
||
};
|
||
Zt(t) && ((Z.value = ``), (Ut.value = ``), (X.value = t));
|
||
}
|
||
// 无动作执行时关闭确认并清空操作密码。
|
||
function Qt() {
|
||
Y.value || ((X.value = null), (Z.value = ``), (Ut.value = ``));
|
||
}
|
||
// 路由/实例/模块/状态变化时废弃待确认动作和旧反馈,密码不跨目标复用。
|
||
function $t() {
|
||
((Wt += 1),
|
||
(X.value = null),
|
||
(Z.value = ``),
|
||
(Ut.value = ``),
|
||
(Y.value = ``));
|
||
}
|
||
watch(
|
||
[() => c.query.id, () => w.value?.id, Ct, () => w.value?.status],
|
||
$t,
|
||
{
|
||
flush: `sync`,
|
||
},
|
||
);
|
||
// 确认提交前后都验证动作快照;后端要求操作密码时留在确认框重试,其他结果关闭并刷新实例。
|
||
async function en() {
|
||
let e = X.value;
|
||
if (!e || Y.value || j.value) return;
|
||
if (T.value || D.value || !Zt(e)) {
|
||
X.value = null;
|
||
return;
|
||
}
|
||
let t = ++Wt,
|
||
n = () => t === Wt && Zt(e);
|
||
((Y.value = e.action),
|
||
(Ut.value = ``),
|
||
(Kt.value = ``),
|
||
(qt.value = ``));
|
||
try {
|
||
if (
|
||
(G.value
|
||
? await K.power(e.action, Z.value)
|
||
: await H.power(e.action, Z.value),
|
||
!n())
|
||
)
|
||
return;
|
||
((X.value = null), Jt(`${e.label}指令已下发`), await q());
|
||
} catch (t) {
|
||
if (!n()) return;
|
||
if (Xt(t)) {
|
||
Ut.value = Z.value
|
||
? `操作密码不正确,请重新输入。`
|
||
: `账户已启用操作密码验证,请输入后重试。`;
|
||
return;
|
||
}
|
||
((X.value = null), Yt(t, `${e.label}失败`));
|
||
} finally {
|
||
t === Wt && ((Y.value = ``), (Z.value = ``));
|
||
}
|
||
}
|
||
// 只有当前模块支持远控且实例 Active 才打开独立远控入口。
|
||
function tn() {
|
||
!D.value &&
|
||
H.caps.value.remoteConsole &&
|
||
V.value &&
|
||
w.value?.status === `Active` &&
|
||
((qt.value = ``), remote_console_t(C, V.value));
|
||
}
|
||
let nn = ref(!1);
|
||
// 打开续费弹窗,具体报价和可用周期交给续费组件处理。
|
||
function rn() {
|
||
((qt.value = ``), (nn.value = !0));
|
||
}
|
||
let an = ref(),
|
||
$ = ref(`overview`),
|
||
on = computed(() => [
|
||
{
|
||
label: `管理面板`,
|
||
items: [
|
||
{
|
||
label: `监控`,
|
||
icon: `pi pi-chart-line`,
|
||
command: () => ($.value = `monitor`),
|
||
},
|
||
{
|
||
label: `访问控制`,
|
||
icon: `pi pi-desktop`,
|
||
command: () => ($.value = `access`),
|
||
},
|
||
...(!U.value && H.caps.value.disk !== !1
|
||
? [
|
||
{
|
||
label: `硬盘管理`,
|
||
icon: `pi pi-database`,
|
||
command: () => ($.value = `disk`),
|
||
},
|
||
]
|
||
: []),
|
||
{
|
||
label: `网络与安全`,
|
||
icon: `pi pi-shield`,
|
||
command: () => ($.value = `network`),
|
||
},
|
||
...(U.value
|
||
? [
|
||
{
|
||
label: `DDoS 防护`,
|
||
icon: `pi pi-shield`,
|
||
command: () => ($.value = `ddos`),
|
||
},
|
||
{
|
||
label: `域名白名单`,
|
||
icon: `pi pi-globe`,
|
||
command: () => ($.value = `domains`),
|
||
},
|
||
{
|
||
label: `计费`,
|
||
icon: `pi pi-wallet`,
|
||
command: () => ($.value = `billing`),
|
||
},
|
||
{
|
||
label: `日志`,
|
||
icon: `pi pi-file`,
|
||
command: () => ($.value = `log`),
|
||
},
|
||
]
|
||
: []),
|
||
...(H.caps.value.snapshot
|
||
? [
|
||
{
|
||
label: `备份与快照`,
|
||
icon: `pi pi-history`,
|
||
command: () => ($.value = `backup`),
|
||
},
|
||
]
|
||
: []),
|
||
...(H.caps.value.upgrade
|
||
? [
|
||
{
|
||
label: `升降级`,
|
||
icon: `pi pi-arrow-up`,
|
||
command: () => ($.value = `billing`),
|
||
},
|
||
]
|
||
: []),
|
||
...(H.caps.value.log
|
||
? [
|
||
{
|
||
label: `日志`,
|
||
icon: `pi pi-file`,
|
||
command: () => ($.value = `log`),
|
||
},
|
||
]
|
||
: []),
|
||
],
|
||
},
|
||
]);
|
||
return (
|
||
onMounted(q),
|
||
onMounted(() => {
|
||
Vt = interval_t(() => {
|
||
document.visibilityState === `visible` && Ht();
|
||
}, 1e4);
|
||
}),
|
||
onUnmounted(() => {
|
||
(Vt && clearInterval(Vt),
|
||
(k = !0),
|
||
(O += 1),
|
||
(F += 1),
|
||
(Gt = !0),
|
||
$t());
|
||
}),
|
||
// 初始骨架、加载错误与主机详情互斥展示;按实际管理模块挂载专用面板,电源确认/续费/支付弹窗使用冻结目标。
|
||
(n, r) => {
|
||
let a = skeleton,
|
||
s = InstanceLoadingShell,
|
||
c = message,
|
||
u = button,
|
||
p = NuxtLink,
|
||
b = tag,
|
||
ee = menu,
|
||
re = OperationNotice,
|
||
de = InstanceServiceInfo,
|
||
pe = CommonManage,
|
||
ve = je,
|
||
O = Me,
|
||
k = Ne,
|
||
be = textarea,
|
||
Se = dialog,
|
||
Te = Pe,
|
||
Ee = inputtext,
|
||
F = OperatePasswordGate,
|
||
ke = Fe;
|
||
return (
|
||
openBlock(),
|
||
createElementBlock(`div`, Ie, [
|
||
unref(T) && !unref(w)
|
||
? (openBlock(),
|
||
createElementBlock(
|
||
Fragment,
|
||
{
|
||
key: 0,
|
||
},
|
||
[
|
||
createElementVNode(`div`, Le, [
|
||
createElementVNode(`div`, Re, [
|
||
createElementVNode(`div`, ze, [
|
||
createElementVNode(`div`, Be, [
|
||
createVNode(a, {
|
||
width: `91px`,
|
||
height: `91px`,
|
||
}),
|
||
]),
|
||
createElementVNode(`div`, Ve, [
|
||
createElementVNode(`div`, He, [
|
||
createVNode(a, {
|
||
width: `180px`,
|
||
height: `27px`,
|
||
}),
|
||
]),
|
||
createElementVNode(`div`, Ue, [
|
||
createVNode(a, {
|
||
width: `150px`,
|
||
height: `24px`,
|
||
}),
|
||
]),
|
||
createElementVNode(`div`, We, [
|
||
(openBlock(),
|
||
createElementBlock(
|
||
Fragment,
|
||
null,
|
||
renderList(
|
||
[
|
||
`区域`,
|
||
`IP 地址`,
|
||
`计算资源`,
|
||
`产品状态`,
|
||
],
|
||
(t) =>
|
||
createElementVNode(
|
||
`div`,
|
||
{
|
||
key: t,
|
||
class: `fact`,
|
||
},
|
||
[
|
||
createElementVNode(
|
||
`label`,
|
||
null,
|
||
toDisplayString(t),
|
||
1,
|
||
),
|
||
createVNode(a, {
|
||
width: `80px`,
|
||
height: `24px`,
|
||
}),
|
||
],
|
||
),
|
||
),
|
||
64,
|
||
)),
|
||
]),
|
||
]),
|
||
]),
|
||
createElementVNode(`div`, Ge, [
|
||
(openBlock(),
|
||
createElementBlock(
|
||
Fragment,
|
||
null,
|
||
renderList(5, (e) =>
|
||
createVNode(a, {
|
||
key: e,
|
||
width: `75px`,
|
||
height: `40px`,
|
||
}),
|
||
),
|
||
64,
|
||
)),
|
||
]),
|
||
]),
|
||
]),
|
||
createVNode(s),
|
||
],
|
||
64,
|
||
))
|
||
: unref(E) && !unref(w)
|
||
? (openBlock(),
|
||
createElementBlock(`div`, Ke, [
|
||
createVNode(
|
||
c,
|
||
{
|
||
severity: `error`,
|
||
closable: !1,
|
||
},
|
||
{
|
||
default: withCtx(() => [
|
||
createTextVNode(toDisplayString(unref(E)), 1),
|
||
]),
|
||
_: 1,
|
||
},
|
||
),
|
||
createVNode(u, {
|
||
label: `重试`,
|
||
icon: `pi pi-refresh`,
|
||
size: `small`,
|
||
severity: `secondary`,
|
||
text: ``,
|
||
onClick: q,
|
||
}),
|
||
]))
|
||
: unref(w)
|
||
? (openBlock(),
|
||
createElementBlock(
|
||
Fragment,
|
||
{
|
||
key: 2,
|
||
},
|
||
[
|
||
createElementVNode(`div`, qe, [
|
||
createVNode(
|
||
p,
|
||
{
|
||
to: unref(Tt).to,
|
||
class: `back`,
|
||
},
|
||
{
|
||
default: withCtx(() => [
|
||
createTextVNode(
|
||
toDisplayString(unref(Tt).label),
|
||
1,
|
||
),
|
||
]),
|
||
_: 1,
|
||
},
|
||
8,
|
||
[`to`],
|
||
),
|
||
createElementVNode(`div`, Je, [
|
||
createElementVNode(`div`, Ye, [
|
||
createElementVNode(`div`, Xe, [
|
||
(r[30] ||= createElementVNode(
|
||
`img`,
|
||
{
|
||
src: Ae,
|
||
alt: ``,
|
||
width: `100`,
|
||
height: `100`,
|
||
},
|
||
null,
|
||
-1,
|
||
)),
|
||
createElementVNode(
|
||
`span`,
|
||
{
|
||
class: normalizeClass([
|
||
`dot`,
|
||
`dot-${unref(Bt).tone}`,
|
||
]),
|
||
role: `img`,
|
||
"aria-label": `产品状态:${unref(Bt).label}`,
|
||
title: unref(Bt).label,
|
||
},
|
||
null,
|
||
10,
|
||
Ze,
|
||
),
|
||
]),
|
||
createElementVNode(`div`, Qe, [
|
||
createElementVNode(`div`, $e, [
|
||
createElementVNode(
|
||
`h2`,
|
||
null,
|
||
toDisplayString(
|
||
unref(product_name_n)(
|
||
unref(w).product_name,
|
||
),
|
||
),
|
||
1,
|
||
),
|
||
createElementVNode(
|
||
`span`,
|
||
et,
|
||
`#` + toDisplayString(unref(w).id),
|
||
1,
|
||
),
|
||
createElementVNode(
|
||
`button`,
|
||
{
|
||
type: `button`,
|
||
class: normalizeClass([
|
||
`copy`,
|
||
{
|
||
ok: unref(J) === `name`,
|
||
},
|
||
]),
|
||
"aria-label":
|
||
unref(J) === `name`
|
||
? `实例名称已复制`
|
||
: `复制实例名称`,
|
||
onClick: (r[0] ||= (e) =>
|
||
Ft(unref(w).name, `name`)),
|
||
},
|
||
[
|
||
...(r[31] ||= [
|
||
createElementVNode(
|
||
`i`,
|
||
{
|
||
class: `pi pi-copy`,
|
||
"aria-hidden": `true`,
|
||
},
|
||
null,
|
||
-1,
|
||
),
|
||
]),
|
||
],
|
||
10,
|
||
tt,
|
||
),
|
||
]),
|
||
createElementVNode(`div`, nt, [
|
||
createElementVNode(
|
||
`span`,
|
||
rt,
|
||
toDisplayString(unref(w).name),
|
||
1,
|
||
),
|
||
createElementVNode(
|
||
`span`,
|
||
it,
|
||
`| ` +
|
||
toDisplayString(
|
||
unref(w).notes || `备注`,
|
||
),
|
||
1,
|
||
),
|
||
createElementVNode(
|
||
`button`,
|
||
{
|
||
class: `copy`,
|
||
type: `button`,
|
||
"aria-label": `编辑备注`,
|
||
onClick: At,
|
||
},
|
||
[
|
||
...(r[32] ||= [
|
||
createElementVNode(
|
||
`i`,
|
||
{
|
||
class: `pi pi-pencil`,
|
||
"aria-hidden": `true`,
|
||
},
|
||
null,
|
||
-1,
|
||
),
|
||
]),
|
||
],
|
||
),
|
||
]),
|
||
createElementVNode(`div`, at, [
|
||
createElementVNode(`div`, ot, [
|
||
(r[33] ||= createElementVNode(
|
||
`label`,
|
||
null,
|
||
`区域`,
|
||
-1,
|
||
)),
|
||
createElementVNode(
|
||
`span`,
|
||
null,
|
||
toDisplayString(unref(It)),
|
||
1,
|
||
),
|
||
]),
|
||
createElementVNode(`div`, st, [
|
||
(r[34] ||= createElementVNode(
|
||
`label`,
|
||
null,
|
||
`IP 地址`,
|
||
-1,
|
||
)),
|
||
unref(De) && !unref(N) && !unref(W)?.ip
|
||
? (openBlock(),
|
||
createElementBlock(
|
||
`span`,
|
||
ct,
|
||
`加载中…`,
|
||
))
|
||
: unref(P) && !unref(W)?.ip
|
||
? (openBlock(),
|
||
createElementBlock(`div`, lt, [
|
||
createElementVNode(
|
||
`span`,
|
||
{
|
||
role: `status`,
|
||
title: unref(P),
|
||
},
|
||
`IP 加载失败`,
|
||
8,
|
||
ut,
|
||
),
|
||
createVNode(u, {
|
||
label: `重试`,
|
||
"aria-label": `重新加载 IP 地址`,
|
||
size: `small`,
|
||
severity: `secondary`,
|
||
text: ``,
|
||
onClick: Et,
|
||
}),
|
||
]))
|
||
: (openBlock(),
|
||
createElementBlock(`span`, dt, [
|
||
createElementVNode(
|
||
`span`,
|
||
ft,
|
||
toDisplayString(unref(Rt)),
|
||
1,
|
||
),
|
||
unref(zt)
|
||
? (openBlock(),
|
||
createElementBlock(
|
||
`button`,
|
||
{
|
||
key: 0,
|
||
type: `button`,
|
||
class: normalizeClass([
|
||
`copy`,
|
||
{
|
||
ok:
|
||
unref(J) === `ip`,
|
||
},
|
||
]),
|
||
"aria-label":
|
||
unref(J) === `ip`
|
||
? `IP 地址已复制`
|
||
: `复制 IP 地址`,
|
||
title:
|
||
unref(J) === `ip`
|
||
? `已复制`
|
||
: `复制 IP 地址`,
|
||
onClick: (r[1] ||= (
|
||
e,
|
||
) =>
|
||
Ft(unref(Rt), `ip`)),
|
||
},
|
||
[
|
||
createElementVNode(
|
||
`i`,
|
||
{
|
||
class:
|
||
normalizeClass(
|
||
unref(J) ===
|
||
`ip`
|
||
? `pi pi-check`
|
||
: `pi pi-copy`,
|
||
),
|
||
"aria-hidden": `true`,
|
||
},
|
||
null,
|
||
2,
|
||
),
|
||
],
|
||
10,
|
||
pt,
|
||
))
|
||
: createCommentVNode(``, !0),
|
||
])),
|
||
]),
|
||
createElementVNode(`div`, mt, [
|
||
(r[35] ||= createElementVNode(
|
||
`label`,
|
||
null,
|
||
`计算资源`,
|
||
-1,
|
||
)),
|
||
createElementVNode(
|
||
`span`,
|
||
null,
|
||
toDisplayString(unref(Lt)),
|
||
1,
|
||
),
|
||
]),
|
||
createElementVNode(`div`, ht, [
|
||
(r[36] ||= createElementVNode(
|
||
`label`,
|
||
null,
|
||
`产品状态`,
|
||
-1,
|
||
)),
|
||
createVNode(
|
||
b,
|
||
{
|
||
class: `instance-product-status`,
|
||
value: unref(Bt).label,
|
||
severity: unref(Bt).severity,
|
||
},
|
||
null,
|
||
8,
|
||
[`value`, `severity`],
|
||
),
|
||
]),
|
||
]),
|
||
]),
|
||
]),
|
||
createElementVNode(
|
||
`div`,
|
||
{
|
||
class: normalizeClass([
|
||
`host-actions`,
|
||
{
|
||
"host-actions-skeleton":
|
||
unref(D) &&
|
||
!unref(B) &&
|
||
unref(w).status === `Active`,
|
||
},
|
||
]),
|
||
},
|
||
[
|
||
unref(w).status === `Unpaid`
|
||
? (openBlock(),
|
||
createBlock(u, {
|
||
key: 0,
|
||
label: `去支付`,
|
||
icon: `pi pi-credit-card`,
|
||
onClick: jt,
|
||
}))
|
||
: unref(D) &&
|
||
!unref(B) &&
|
||
unref(w).status === `Active`
|
||
? (openBlock(),
|
||
createElementBlock(
|
||
Fragment,
|
||
{
|
||
key: 1,
|
||
},
|
||
renderList(5, (e) =>
|
||
createVNode(a, {
|
||
key: e,
|
||
width: `75px`,
|
||
height: `40px`,
|
||
}),
|
||
),
|
||
64,
|
||
))
|
||
: unref(V) &&
|
||
unref(w).status === `Active`
|
||
? (openBlock(),
|
||
createElementBlock(
|
||
Fragment,
|
||
{
|
||
key: 2,
|
||
},
|
||
[
|
||
unref(H).caps.value.power
|
||
? (openBlock(),
|
||
createBlock(
|
||
u,
|
||
{
|
||
key: 0,
|
||
label: `开机`,
|
||
icon: `pi pi-power-off`,
|
||
severity: `success`,
|
||
outlined: ``,
|
||
loading:
|
||
unref(Y) === `on`,
|
||
disabled:
|
||
!!unref(Y) ||
|
||
unref(D) ||
|
||
unref(j),
|
||
onClick: (r[2] ||= (
|
||
e,
|
||
) => Q(`on`)),
|
||
},
|
||
null,
|
||
8,
|
||
[`loading`, `disabled`],
|
||
))
|
||
: createCommentVNode(``, !0),
|
||
unref(H).caps.value.power
|
||
? (openBlock(),
|
||
createBlock(
|
||
u,
|
||
{
|
||
key: 1,
|
||
label: `关机`,
|
||
icon: `pi pi-power-off`,
|
||
severity: `danger`,
|
||
outlined: ``,
|
||
loading:
|
||
unref(Y) === `off`,
|
||
disabled:
|
||
!!unref(Y) ||
|
||
unref(D) ||
|
||
unref(j),
|
||
onClick: (r[3] ||= (
|
||
e,
|
||
) => Q(`off`)),
|
||
},
|
||
null,
|
||
8,
|
||
[`loading`, `disabled`],
|
||
))
|
||
: createCommentVNode(``, !0),
|
||
unref(H).caps.value.power
|
||
? (openBlock(),
|
||
createBlock(
|
||
u,
|
||
{
|
||
key: 2,
|
||
label: `重启`,
|
||
icon: `pi pi-refresh`,
|
||
severity: `secondary`,
|
||
outlined: ``,
|
||
loading:
|
||
unref(Y) === `reboot`,
|
||
disabled:
|
||
!!unref(Y) ||
|
||
unref(D) ||
|
||
unref(j),
|
||
onClick: (r[4] ||= (
|
||
e,
|
||
) => Q(`reboot`)),
|
||
},
|
||
null,
|
||
8,
|
||
[`loading`, `disabled`],
|
||
))
|
||
: createCommentVNode(``, !0),
|
||
unref(H).caps.value
|
||
.remoteConsole
|
||
? (openBlock(),
|
||
createBlock(
|
||
u,
|
||
{
|
||
key: 3,
|
||
label: `VNC`,
|
||
icon: `pi pi-desktop`,
|
||
severity: `secondary`,
|
||
outlined: ``,
|
||
disabled: unref(D),
|
||
onClick: tn,
|
||
},
|
||
null,
|
||
8,
|
||
[`disabled`],
|
||
))
|
||
: createCommentVNode(``, !0),
|
||
createVNode(u, {
|
||
label: `续费`,
|
||
icon: `pi pi-wallet`,
|
||
onClick: rn,
|
||
}),
|
||
createVNode(u, {
|
||
label: `更多`,
|
||
icon: `pi pi-ellipsis-h`,
|
||
severity: `secondary`,
|
||
outlined: ``,
|
||
onClick: (r[5] ||= (e) =>
|
||
unref(an).toggle(e)),
|
||
}),
|
||
],
|
||
64,
|
||
))
|
||
: unref(U) &&
|
||
unref(w).status === `Active`
|
||
? (openBlock(),
|
||
createElementBlock(
|
||
Fragment,
|
||
{
|
||
key: 3,
|
||
},
|
||
[
|
||
createVNode(
|
||
u,
|
||
{
|
||
label: `开机`,
|
||
icon: `pi pi-power-off`,
|
||
severity: `success`,
|
||
outlined: ``,
|
||
disabled:
|
||
!unref(W)?.control,
|
||
onClick: (r[6] ||= (e) =>
|
||
Q(`on`)),
|
||
},
|
||
null,
|
||
8,
|
||
[`disabled`],
|
||
),
|
||
createVNode(
|
||
u,
|
||
{
|
||
label: `关机`,
|
||
icon: `pi pi-power-off`,
|
||
severity: `danger`,
|
||
outlined: ``,
|
||
disabled:
|
||
!unref(W)?.control,
|
||
onClick: (r[7] ||= (e) =>
|
||
Q(`off`)),
|
||
},
|
||
null,
|
||
8,
|
||
[`disabled`],
|
||
),
|
||
createVNode(
|
||
u,
|
||
{
|
||
label: `重启`,
|
||
icon: `pi pi-refresh`,
|
||
severity: `secondary`,
|
||
outlined: ``,
|
||
disabled:
|
||
!unref(W)?.control,
|
||
onClick: (r[8] ||= (e) =>
|
||
Q(`reboot`)),
|
||
},
|
||
null,
|
||
8,
|
||
[`disabled`],
|
||
),
|
||
createVNode(
|
||
u,
|
||
{
|
||
label: `VNC`,
|
||
icon: `pi pi-desktop`,
|
||
severity: `secondary`,
|
||
outlined: ``,
|
||
disabled:
|
||
!unref(W)?.control,
|
||
onClick: (r[9] ||= (e) =>
|
||
unref(
|
||
xt,
|
||
)?.requestAction(
|
||
`vnc`,
|
||
)),
|
||
},
|
||
null,
|
||
8,
|
||
[`disabled`],
|
||
),
|
||
createVNode(
|
||
u,
|
||
{
|
||
label: `续费`,
|
||
icon: `pi pi-wallet`,
|
||
disabled:
|
||
!!unref(w)
|
||
.renew_forbidden,
|
||
onClick: rn,
|
||
},
|
||
null,
|
||
8,
|
||
[`disabled`],
|
||
),
|
||
createVNode(u, {
|
||
label: `更多`,
|
||
icon: `pi pi-ellipsis-h`,
|
||
severity: `secondary`,
|
||
outlined: ``,
|
||
onClick: (r[10] ||= (e) =>
|
||
unref(an).toggle(e)),
|
||
}),
|
||
],
|
||
64,
|
||
))
|
||
: unref(G) &&
|
||
unref(w).status === `Active`
|
||
? (openBlock(),
|
||
createElementBlock(
|
||
Fragment,
|
||
{
|
||
key: 4,
|
||
},
|
||
[
|
||
unref(K).can(`on`)
|
||
? (openBlock(),
|
||
createBlock(
|
||
u,
|
||
{
|
||
key: 0,
|
||
label: `开机`,
|
||
icon: `pi pi-power-off`,
|
||
severity: `success`,
|
||
outlined: ``,
|
||
loading:
|
||
unref(Y) === `on`,
|
||
disabled:
|
||
!!unref(Y) ||
|
||
unref(D) ||
|
||
unref(j),
|
||
onClick: (r[11] ||=
|
||
(e) => Q(`on`)),
|
||
},
|
||
null,
|
||
8,
|
||
[
|
||
`loading`,
|
||
`disabled`,
|
||
],
|
||
))
|
||
: createCommentVNode(
|
||
``,
|
||
!0,
|
||
),
|
||
unref(K).can(`off`)
|
||
? (openBlock(),
|
||
createBlock(
|
||
u,
|
||
{
|
||
key: 1,
|
||
label: `关机`,
|
||
icon: `pi pi-power-off`,
|
||
severity: `danger`,
|
||
outlined: ``,
|
||
loading:
|
||
unref(Y) ===
|
||
`off`,
|
||
disabled:
|
||
!!unref(Y) ||
|
||
unref(D) ||
|
||
unref(j),
|
||
onClick: (r[12] ||=
|
||
(e) => Q(`off`)),
|
||
},
|
||
null,
|
||
8,
|
||
[
|
||
`loading`,
|
||
`disabled`,
|
||
],
|
||
))
|
||
: createCommentVNode(
|
||
``,
|
||
!0,
|
||
),
|
||
unref(K).can(`reboot`)
|
||
? (openBlock(),
|
||
createBlock(
|
||
u,
|
||
{
|
||
key: 2,
|
||
label: `重启`,
|
||
icon: `pi pi-refresh`,
|
||
severity: `secondary`,
|
||
outlined: ``,
|
||
loading:
|
||
unref(Y) ===
|
||
`reboot`,
|
||
disabled:
|
||
!!unref(Y) ||
|
||
unref(D) ||
|
||
unref(j),
|
||
onClick: (r[13] ||=
|
||
(e) =>
|
||
Q(`reboot`)),
|
||
},
|
||
null,
|
||
8,
|
||
[
|
||
`loading`,
|
||
`disabled`,
|
||
],
|
||
))
|
||
: createCommentVNode(
|
||
``,
|
||
!0,
|
||
),
|
||
],
|
||
64,
|
||
))
|
||
: createCommentVNode(``, !0),
|
||
],
|
||
2,
|
||
),
|
||
createVNode(
|
||
ee,
|
||
{
|
||
ref_key: `moreMenu`,
|
||
ref: an,
|
||
model: unref(on),
|
||
popup: ``,
|
||
},
|
||
null,
|
||
8,
|
||
[`model`],
|
||
),
|
||
]),
|
||
!unref(V) &&
|
||
!unref(U) &&
|
||
unref(instance_status_n)(unref(w))
|
||
? (openBlock(),
|
||
createBlock(
|
||
c,
|
||
{
|
||
key: 0,
|
||
severity: `warn`,
|
||
closable: !1,
|
||
},
|
||
{
|
||
default: withCtx(() => [
|
||
createTextVNode(
|
||
`暂停原因:` +
|
||
toDisplayString(
|
||
unref(instance_status_n)(
|
||
unref(w),
|
||
),
|
||
),
|
||
1,
|
||
),
|
||
]),
|
||
_: 1,
|
||
},
|
||
))
|
||
: !unref(V) &&
|
||
!unref(U) &&
|
||
unref(w).status === `Pending`
|
||
? (openBlock(),
|
||
createBlock(
|
||
c,
|
||
{
|
||
key: 1,
|
||
severity: `info`,
|
||
closable: !1,
|
||
},
|
||
{
|
||
default: withCtx(() => [
|
||
...(r[37] ||= [
|
||
createTextVNode(
|
||
`实例开通中,请稍候。`,
|
||
-1,
|
||
),
|
||
]),
|
||
]),
|
||
_: 1,
|
||
},
|
||
))
|
||
: createCommentVNode(``, !0),
|
||
unref(Kt)
|
||
? (openBlock(),
|
||
createBlock(
|
||
re,
|
||
{
|
||
key: 2,
|
||
message: unref(Kt),
|
||
},
|
||
null,
|
||
8,
|
||
[`message`],
|
||
))
|
||
: createCommentVNode(``, !0),
|
||
unref(qt)
|
||
? (openBlock(),
|
||
createBlock(
|
||
re,
|
||
{
|
||
key: 3,
|
||
severity: `error`,
|
||
message: unref(qt),
|
||
},
|
||
null,
|
||
8,
|
||
[`message`],
|
||
))
|
||
: createCommentVNode(``, !0),
|
||
unref(K).error.value && !unref(St)
|
||
? (openBlock(),
|
||
createBlock(
|
||
c,
|
||
{
|
||
key: 4,
|
||
severity: `error`,
|
||
closable: !1,
|
||
},
|
||
{
|
||
default: withCtx(() => [
|
||
createTextVNode(
|
||
toDisplayString(unref(K).error.value),
|
||
1,
|
||
),
|
||
createVNode(u, {
|
||
label: `重试`,
|
||
text: ``,
|
||
onClick: q,
|
||
}),
|
||
]),
|
||
_: 1,
|
||
},
|
||
))
|
||
: createCommentVNode(``, !0),
|
||
unref(E)
|
||
? (openBlock(),
|
||
createBlock(
|
||
c,
|
||
{
|
||
key: 5,
|
||
severity: `error`,
|
||
closable: !1,
|
||
class: `msg`,
|
||
},
|
||
{
|
||
default: withCtx(() => [
|
||
createTextVNode(
|
||
toDisplayString(unref(E)),
|
||
1,
|
||
),
|
||
createVNode(u, {
|
||
label: `重试`,
|
||
text: ``,
|
||
onClick: q,
|
||
}),
|
||
]),
|
||
_: 1,
|
||
},
|
||
))
|
||
: createCommentVNode(``, !0),
|
||
]),
|
||
unref(D) &&
|
||
!unref(V) &&
|
||
!unref(U) &&
|
||
!unref(St) &&
|
||
!unref(M)
|
||
? (openBlock(),
|
||
createBlock(s, {
|
||
key: 0,
|
||
}))
|
||
: createCommentVNode(``, !0),
|
||
!unref(V) &&
|
||
!unref(U) &&
|
||
(unref(w).status !== `Active` || unref(E))
|
||
? (openBlock(),
|
||
createBlock(
|
||
de,
|
||
{
|
||
key: 1,
|
||
host: unref(w),
|
||
module: unref(B),
|
||
info: unref(K).metadata.value ?? unref(A),
|
||
onPay: Mt,
|
||
},
|
||
null,
|
||
8,
|
||
[`host`, `module`, `info`],
|
||
))
|
||
: createCommentVNode(``, !0),
|
||
unref(M) && unref(w)
|
||
? (openBlock(),
|
||
createBlock(
|
||
pe,
|
||
{
|
||
key: `${unref(C)}-${unref(Nt)}`,
|
||
"host-id": unref(C),
|
||
module: unref(M),
|
||
host: unref(w),
|
||
data:
|
||
unref(M) === `remf_finance_common`
|
||
? unref(K).metadata.value
|
||
: unref(A),
|
||
loading: unref(D),
|
||
error: unref(ye) || unref(K).error.value,
|
||
busy: !!unref(Y) || !!unref(X),
|
||
onBusy: (r[14] ||= (e) => (j.value = e)),
|
||
onRefresh: q,
|
||
onPay: Mt,
|
||
},
|
||
null,
|
||
8,
|
||
[
|
||
`host-id`,
|
||
`module`,
|
||
`host`,
|
||
`data`,
|
||
`loading`,
|
||
`error`,
|
||
`busy`,
|
||
],
|
||
))
|
||
: createCommentVNode(``, !0),
|
||
unref(V) && unref(w)
|
||
? (openBlock(),
|
||
createBlock(
|
||
Suspense,
|
||
{
|
||
key: 3,
|
||
},
|
||
{
|
||
fallback: withCtx(() => [createVNode(s)]),
|
||
default: withCtx(() => [
|
||
(openBlock(),
|
||
createBlock(
|
||
ve,
|
||
{
|
||
key: `${unref(C)}-${unref(Nt)}`,
|
||
"product-state": unref(Bt),
|
||
tab: unref($),
|
||
"onUpdate:tab": (r[15] ||= (e) =>
|
||
isRef($) ? ($.value = e) : null),
|
||
"host-id": unref(C),
|
||
"product-id": unref(bt),
|
||
host: unref(w),
|
||
module: unref(V),
|
||
detail: unref(H),
|
||
onRefresh: q,
|
||
onPay: Mt,
|
||
},
|
||
null,
|
||
8,
|
||
[
|
||
`product-state`,
|
||
`tab`,
|
||
`host-id`,
|
||
`product-id`,
|
||
`host`,
|
||
`module`,
|
||
`detail`,
|
||
],
|
||
)),
|
||
]),
|
||
_: 1,
|
||
},
|
||
))
|
||
: unref(U)
|
||
? (openBlock(),
|
||
createBlock(
|
||
Suspense,
|
||
{
|
||
key: 4,
|
||
},
|
||
{
|
||
fallback: withCtx(() => [
|
||
createVNode(s, {
|
||
dcim: ``,
|
||
}),
|
||
]),
|
||
default: withCtx(() => [
|
||
createVNode(
|
||
O,
|
||
{
|
||
"product-state": unref(Bt),
|
||
ref_key: `dcimManage`,
|
||
ref: xt,
|
||
tab: unref($),
|
||
"onUpdate:tab": (r[16] ||= (e) =>
|
||
isRef($) ? ($.value = e) : null),
|
||
"host-id": unref(C),
|
||
"product-id": unref(bt),
|
||
host: unref(w),
|
||
module: unref(U),
|
||
onPresentation: (r[17] ||= (e) =>
|
||
(W.value = e)),
|
||
onRenew: rn,
|
||
onRefresh: q,
|
||
},
|
||
null,
|
||
8,
|
||
[
|
||
`product-state`,
|
||
`tab`,
|
||
`host-id`,
|
||
`product-id`,
|
||
`host`,
|
||
`module`,
|
||
],
|
||
),
|
||
]),
|
||
_: 1,
|
||
},
|
||
))
|
||
: unref(St) && unref(w)
|
||
? (openBlock(),
|
||
createBlock(
|
||
Suspense,
|
||
{
|
||
key: 5,
|
||
},
|
||
{
|
||
fallback: withCtx(() => [
|
||
createVNode(s, {
|
||
dcim: ``,
|
||
}),
|
||
]),
|
||
default: withCtx(() => [
|
||
createVNode(
|
||
k,
|
||
{
|
||
tab: unref($),
|
||
"onUpdate:tab": (r[18] ||= (e) =>
|
||
isRef($)
|
||
? ($.value = e)
|
||
: null),
|
||
"host-id": unref(C),
|
||
host: unref(w),
|
||
data: unref(K).metadata.value,
|
||
loading: unref(K).loading.value,
|
||
error: unref(K).error.value,
|
||
busy: !!unref(Y) || unref(D),
|
||
"product-state": unref(Bt),
|
||
onPresentation: (r[19] ||= (e) =>
|
||
(W.value = e)),
|
||
onRefresh: q,
|
||
onRenew: rn,
|
||
},
|
||
null,
|
||
8,
|
||
[
|
||
`tab`,
|
||
`host-id`,
|
||
`host`,
|
||
`data`,
|
||
`loading`,
|
||
`error`,
|
||
`busy`,
|
||
`product-state`,
|
||
],
|
||
),
|
||
]),
|
||
_: 1,
|
||
},
|
||
))
|
||
: createCommentVNode(``, !0),
|
||
createVNode(
|
||
Se,
|
||
{
|
||
visible: unref(L),
|
||
"onUpdate:visible": [
|
||
(r[22] ||= (e) =>
|
||
isRef(L) ? (L.value = e) : null),
|
||
(r[23] ||= (e) => {
|
||
(e && (z.value = ``), (L.value = e));
|
||
}),
|
||
],
|
||
header: `编辑备注`,
|
||
modal: ``,
|
||
style: {
|
||
width: `448px`,
|
||
},
|
||
draggable: !1,
|
||
closable: !unref(R),
|
||
},
|
||
{
|
||
footer: withCtx(() => [
|
||
createVNode(
|
||
u,
|
||
{
|
||
label: `取消`,
|
||
severity: `secondary`,
|
||
text: ``,
|
||
disabled: unref(R),
|
||
onClick: (r[21] ||= (e) => {
|
||
((z.value = ``), (L.value = !1));
|
||
}),
|
||
},
|
||
null,
|
||
8,
|
||
[`disabled`],
|
||
),
|
||
createVNode(
|
||
u,
|
||
{
|
||
label: `保存`,
|
||
loading: unref(R),
|
||
onClick: kt,
|
||
},
|
||
null,
|
||
8,
|
||
[`loading`],
|
||
),
|
||
]),
|
||
default: withCtx(() => [
|
||
(r[38] ||= createElementVNode(
|
||
`label`,
|
||
{
|
||
for: `host-notes`,
|
||
class: `notes-label`,
|
||
},
|
||
`备注`,
|
||
-1,
|
||
)),
|
||
unref(z)
|
||
? (openBlock(),
|
||
createBlock(
|
||
re,
|
||
{
|
||
key: 0,
|
||
severity: `error`,
|
||
message: unref(z),
|
||
},
|
||
null,
|
||
8,
|
||
[`message`],
|
||
))
|
||
: createCommentVNode(``, !0),
|
||
createVNode(
|
||
be,
|
||
{
|
||
id: `host-notes`,
|
||
modelValue: unref(I),
|
||
"onUpdate:modelValue": (r[20] ||= (e) =>
|
||
isRef(I) ? (I.value = e) : null),
|
||
rows: `3`,
|
||
autoResize: ``,
|
||
fluid: ``,
|
||
placeholder: `添加备注(仅自己可见)`,
|
||
disabled: unref(R),
|
||
},
|
||
null,
|
||
8,
|
||
[`modelValue`, `disabled`],
|
||
),
|
||
]),
|
||
_: 1,
|
||
},
|
||
8,
|
||
[`visible`, `closable`],
|
||
),
|
||
],
|
||
64,
|
||
))
|
||
: createCommentVNode(``, !0),
|
||
unref(Oe)
|
||
? (openBlock(),
|
||
createBlock(
|
||
Te,
|
||
{
|
||
key: 3,
|
||
modelValue: unref(Oe),
|
||
"onUpdate:modelValue": (r[24] ||= (e) =>
|
||
isRef(Oe) ? (Oe.value = e) : null),
|
||
"order-id": unref(vt),
|
||
amount: unref(yt),
|
||
onSuccess: Pt,
|
||
},
|
||
null,
|
||
8,
|
||
[`modelValue`, `order-id`, `amount`],
|
||
))
|
||
: createCommentVNode(``, !0),
|
||
createVNode(
|
||
Se,
|
||
{
|
||
visible: !!unref(X),
|
||
header: `确认电源操作`,
|
||
modal: ``,
|
||
style: {
|
||
width: `440px`,
|
||
},
|
||
draggable: !1,
|
||
closable: !unref(Y),
|
||
"close-on-escape": !unref(Y),
|
||
"onUpdate:visible": (r[27] ||= (e) => {
|
||
e || Qt();
|
||
}),
|
||
},
|
||
{
|
||
footer: withCtx(() => [
|
||
createVNode(
|
||
u,
|
||
{
|
||
label: `取消`,
|
||
severity: `secondary`,
|
||
outlined: ``,
|
||
autofocus: ``,
|
||
disabled: !!unref(Y),
|
||
onClick: Qt,
|
||
},
|
||
null,
|
||
8,
|
||
[`disabled`],
|
||
),
|
||
createVNode(
|
||
u,
|
||
{
|
||
label: `确认${unref(X)?.label || ``}`,
|
||
severity:
|
||
unref(X)?.action === `on` ? `success` : `danger`,
|
||
loading: !!unref(Y),
|
||
disabled: !!unref(Y),
|
||
onClick: en,
|
||
},
|
||
null,
|
||
8,
|
||
[`label`, `severity`, `loading`, `disabled`],
|
||
),
|
||
]),
|
||
default: withCtx(() => [
|
||
unref(X)
|
||
? (openBlock(),
|
||
createElementBlock(`div`, gt, [
|
||
createElementVNode(`p`, null, [
|
||
(r[39] ||= createTextVNode(`确认对实例「`, -1)),
|
||
createElementVNode(
|
||
`strong`,
|
||
null,
|
||
toDisplayString(unref(X).hostName),
|
||
1,
|
||
),
|
||
createTextVNode(
|
||
`」(#` +
|
||
toDisplayString(unref(X).hostId) +
|
||
`)执行`,
|
||
1,
|
||
),
|
||
createElementVNode(
|
||
`strong`,
|
||
null,
|
||
toDisplayString(unref(X).label),
|
||
1,
|
||
),
|
||
(r[40] ||= createTextVNode(`?`, -1)),
|
||
]),
|
||
createElementVNode(
|
||
`p`,
|
||
null,
|
||
toDisplayString(
|
||
unref(X).action === `on`
|
||
? `将启动此实例,请等待操作系统完成启动。`
|
||
: unref(X).action === `off`
|
||
? `关机后,实例上的服务将停止运行。`
|
||
: `重启期间,实例上的服务将暂时中断。`,
|
||
),
|
||
1,
|
||
),
|
||
unref(Ct)
|
||
? (openBlock(),
|
||
createElementBlock(
|
||
Fragment,
|
||
{
|
||
key: 0,
|
||
},
|
||
[
|
||
createVNode(F, null, {
|
||
default: withCtx(() => [
|
||
(r[41] ||= createElementVNode(
|
||
`label`,
|
||
{
|
||
for: `power-operate-password`,
|
||
},
|
||
`操作密码(如已设置)`,
|
||
-1,
|
||
)),
|
||
createVNode(
|
||
Ee,
|
||
{
|
||
id: `power-operate-password`,
|
||
modelValue: unref(Z),
|
||
"onUpdate:modelValue": (r[25] ||= (
|
||
e,
|
||
) =>
|
||
isRef(Z) ? (Z.value = e) : null),
|
||
type: `password`,
|
||
autocomplete: `off`,
|
||
disabled: !!unref(Y),
|
||
fluid: ``,
|
||
onInput: (r[26] ||= (e) =>
|
||
(Ut.value = ``)),
|
||
},
|
||
null,
|
||
8,
|
||
[`modelValue`, `disabled`],
|
||
),
|
||
]),
|
||
_: 1,
|
||
}),
|
||
unref(Ut)
|
||
? (openBlock(),
|
||
createElementBlock(
|
||
`small`,
|
||
_t,
|
||
toDisplayString(unref(Ut)),
|
||
1,
|
||
))
|
||
: createCommentVNode(``, !0),
|
||
],
|
||
64,
|
||
))
|
||
: createCommentVNode(``, !0),
|
||
]))
|
||
: createCommentVNode(``, !0),
|
||
]),
|
||
_: 1,
|
||
},
|
||
8,
|
||
[`visible`, `closable`, `close-on-escape`],
|
||
),
|
||
unref(nn)
|
||
? (openBlock(),
|
||
createBlock(
|
||
ke,
|
||
{
|
||
key: 4,
|
||
modelValue: unref(nn),
|
||
"onUpdate:modelValue": (r[28] ||= (e) =>
|
||
isRef(nn) ? (nn.value = e) : null),
|
||
"host-id": unref(C),
|
||
onPaid: (r[29] ||= (e) => {
|
||
(Jt(`续费订单已创建,请前往订单页完成支付`),
|
||
(`navigateTo` in n
|
||
? n.navigateTo
|
||
: unref(navigateTo))(`/orders`));
|
||
}),
|
||
},
|
||
null,
|
||
8,
|
||
[`modelValue`, `host-id`],
|
||
))
|
||
: createCommentVNode(``, !0),
|
||
])
|
||
);
|
||
}
|
||
);
|
||
},
|
||
}),
|
||
[[`__scopeId`, `data-v-b18590a1`]],
|
||
);
|
||
export {};
|
||
export default vt;
|
||
</script>
|