Files
cneicy 42dfead9cd
前端验证 / verify (push) Failing after 15m3s
feat(ui): 优化控制台响应式布局与视觉体验
- 统一页面标题、圆角、字体和响应式断点,调整暗色主题及图表配色
- 新增表格列标签插件,在窄屏下将表格转换为卡片布局,优化实例、订单、工单等列表展示
- 支持移动端点击订单行进入详情,并完善订单凭据的打印布局
- 在财务中心展示本月及累计消费,补充充值关闭时的提示
- 优化工单详情布局,将附件上传入口整合至富文本编辑器工具栏
- 调整实例操作按钮、SSH 密钥操作及安全菜单图标
- 为多个页面显式导入 definePageMeta,完善页面元数据声明
2026-11-07 00:09:57 +08:00

3028 lines
123 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script>
/**
* 实例详情调度页:先确认主机与商品,再解析实际管理模块;统一展示数据与能力开关,云/物理/通用旧模块分别委派管理组件。权限展示不替代后端鉴权。
*/
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>