942 lines
36 KiB
Vue
942 lines
36 KiB
Vue
<script>
|
|
/**
|
|
* 同源远程控制台:父级提供实例、模块及操作密码,通过 update:visible 关闭面板。
|
|
* 浏览器只向 /remote-console/sessions 申请短期会话,再以服务端返回的同源路径连接 noVNC。
|
|
* 这里不直连供应商 VNC 地址;部署时 HTTP 与 WebSocket 路径都需要网关反向代理。
|
|
*/
|
|
import "~/assets/styles/RemoteConsole.DLmX5UZu.css";
|
|
import { toDisplayString } from "vue";
|
|
import { onMounted } from "vue";
|
|
import { useId } from "vue";
|
|
import { normalizeClass } from "vue";
|
|
import { onBeforeUnmount } from "vue";
|
|
import { watch } from "vue";
|
|
import { createBlock } from "vue";
|
|
import { ref } from "vue";
|
|
import { 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 { withModifiers } from "vue";
|
|
import { loadModule } from "~/utils/load-module.js";
|
|
import { useAuth } from "~/lib/auth.js";
|
|
import button from "primevue/button";
|
|
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
|
|
import inputtext from "primevue/inputtext";
|
|
var T = /^[a-f0-9]{64}$/;
|
|
function E(e, n) {
|
|
// 独立连接状态机;d 是连接代次,h 保存需要删除的网关会话,g 是当前 RFB 客户端。
|
|
let r = useAuth(),
|
|
o = ref(`idle`),
|
|
c = ref(``),
|
|
l = ref(!0),
|
|
u = ref([]),
|
|
d = 0,
|
|
f = !1,
|
|
p = null,
|
|
m = null,
|
|
h = null,
|
|
g = null,
|
|
_ = [];
|
|
function v() {
|
|
(m !== null && clearTimeout(m), (m = null));
|
|
}
|
|
async function y(e, t) {
|
|
// 使用创建会话时的 token 做尽力释放;keepalive 允许页面离开时仍发送清理请求。
|
|
if (T.test(e))
|
|
try {
|
|
await fetch(`/remote-console/sessions/${e}`, {
|
|
method: `DELETE`,
|
|
headers: {
|
|
Authorization: `Bearer ${t}`,
|
|
},
|
|
credentials: `same-origin`,
|
|
cache: `no-store`,
|
|
keepalive: !0,
|
|
});
|
|
} catch {}
|
|
}
|
|
function S() {
|
|
// 统一释放入口先推进代次,再中止请求、断开 RFB、移除事件并删除远端会话。
|
|
if ((d++, p?.abort(), (p = null), v(), g)) {
|
|
for (let [e, t] of _) g.removeEventListener(e, t);
|
|
try {
|
|
g.disconnect();
|
|
} catch {}
|
|
g = null;
|
|
}
|
|
if (((_ = []), (u.value = []), h)) {
|
|
let e = h;
|
|
((h = null), y(e.id, e.token));
|
|
}
|
|
}
|
|
function C() {
|
|
(S(), (c.value = ``), (o.value = `disconnected`));
|
|
}
|
|
function w(e) {
|
|
(S(), (c.value = e), (o.value = `error`));
|
|
}
|
|
function E(e) {
|
|
// 建立连接或提交凭据后均有 45 秒上限,旧连接定时器不能终止新的连接。
|
|
(v(),
|
|
(m = setTimeout(() => {
|
|
e === d && !f && w(`连接超时,请重新连接。`);
|
|
}, 45e3)));
|
|
}
|
|
function D(e, t) {
|
|
// 仅展示有限长度的中文网关错误,避免把供应商地址、凭据或内部异常原样暴露。
|
|
if (t === 401) return `登录已失效,请重新登录后打开控制台。`;
|
|
if (t === 403) return `暂时无法访问此实例的控制台,请核对账号后重试。`;
|
|
let n = e && typeof e == `object` && `error` in e ? e.error : null;
|
|
return typeof n == `string` &&
|
|
/^[\u3400-\u9fff\s,。!?、:()…0-9-]{1,100}$/u.test(n)
|
|
? n
|
|
: `控制台暂时无法连接,请稍后重试。`;
|
|
}
|
|
async function O() {
|
|
// 登录状态、实例、模块和挂载节点共同构成连接身份;异步阶段每次回写前都重新核对。
|
|
if ((S(), (c.value = ``), f || !n.visible() || !e.value)) {
|
|
o.value = `idle`;
|
|
return;
|
|
}
|
|
let t = localStorage.getItem(`jwt`);
|
|
if (!t || r.token !== t) {
|
|
((o.value = `error`), (c.value = `请重新登录后打开控制台。`));
|
|
return;
|
|
}
|
|
let i = String(n.hostId()),
|
|
a = n.module(),
|
|
s = e.value;
|
|
if (!/^\d+$/.test(i) || Number(i) < 1 || !a) {
|
|
((o.value = `error`), (c.value = `实例信息尚未就绪,请重新打开控制台。`));
|
|
return;
|
|
}
|
|
let m = d,
|
|
x = () =>
|
|
m === d &&
|
|
!f &&
|
|
n.visible() &&
|
|
e.value === s &&
|
|
String(n.hostId()) === i &&
|
|
n.module() === a &&
|
|
r.token === t &&
|
|
localStorage.getItem(`jwt`) === t;
|
|
((o.value = `creating`), (p = new AbortController()));
|
|
let C = p.signal;
|
|
E(m);
|
|
try {
|
|
let e = await fetch(`/remote-console/sessions`, {
|
|
method: `POST`,
|
|
credentials: `same-origin`,
|
|
cache: `no-store`,
|
|
signal: C,
|
|
headers: {
|
|
Authorization: `Bearer ${t}`,
|
|
"Content-Type": `application/json`,
|
|
},
|
|
body: JSON.stringify({
|
|
hostId: i,
|
|
module: a,
|
|
...(n.operatePassword()
|
|
? {
|
|
client_operate_password: n.operatePassword(),
|
|
}
|
|
: {}),
|
|
}),
|
|
}),
|
|
r = await e.json().catch(() => null),
|
|
d =
|
|
typeof r?.sessionId == `string` && T.test(r.sessionId)
|
|
? r.sessionId
|
|
: ``;
|
|
if (!x()) {
|
|
// 创建成功但用户已关闭或切换实例时,仍要回收刚生成的服务端会话。
|
|
d && y(d, t);
|
|
return;
|
|
}
|
|
if (!e.ok) {
|
|
(d && y(d, t), w(D(r, e.status)));
|
|
return;
|
|
}
|
|
if (
|
|
(d &&
|
|
(h = {
|
|
id: d,
|
|
token: t,
|
|
}),
|
|
!d || r?.websocketPath !== `/remote-console/sessions/${d}/socket`)
|
|
) {
|
|
w(`控制台连接信息无效,请重新连接。`);
|
|
return;
|
|
}
|
|
let { default: f } = await loadModule(
|
|
// 只在实际连接时加载 noVNC,避免把远控依赖放进所有页面的首屏执行路径。
|
|
async () => {
|
|
let { default: e } = await import("@novnc/novnc");
|
|
return {
|
|
default: e,
|
|
};
|
|
},
|
|
[],
|
|
import.meta.url,
|
|
);
|
|
if (!x()) return;
|
|
o.value = `connecting`;
|
|
let p = new f(
|
|
s,
|
|
`${window.location.protocol === `https:` ? `wss:` : `ws:`}//${window.location.host}${r.websocketPath}`,
|
|
{
|
|
...(typeof r.credentials?.password == `string`
|
|
? {
|
|
credentials: {
|
|
password: r.credentials.password,
|
|
},
|
|
}
|
|
: {}),
|
|
},
|
|
);
|
|
((g = p), (p.scaleViewport = l.value), (p.resizeSession = !1));
|
|
let m = (e, t) => {
|
|
(p.addEventListener(e, t), _.push([e, t]));
|
|
};
|
|
(m(`connect`, () => {
|
|
x() && (v(), (u.value = []), (o.value = `connected`));
|
|
}),
|
|
m(`disconnect`, () => {
|
|
if (!x()) return;
|
|
let e = o.value === `connected`;
|
|
(S(),
|
|
(o.value = e ? `disconnected` : `error`),
|
|
(c.value = e ? `` : `连接未能建立,请重新连接。`));
|
|
}),
|
|
m(`credentialsrequired`, (e) => {
|
|
if (!x()) return;
|
|
v();
|
|
let t = e.detail?.types;
|
|
if (
|
|
((u.value = Array.isArray(t)
|
|
? t.filter((e) => [`username`, `password`, `target`].includes(e))
|
|
: [`password`]),
|
|
!u.value.length)
|
|
) {
|
|
w(`此控制台暂不支持当前验证方式,请联系支持。`);
|
|
return;
|
|
}
|
|
o.value = `credentials`;
|
|
}),
|
|
m(`securityfailure`, () => {
|
|
x() && w(`控制台验证失败,请重新连接。`);
|
|
}));
|
|
} catch {
|
|
x() && w(`控制台暂时无法连接,请稍后重试。`);
|
|
}
|
|
}
|
|
function k(e) {
|
|
// 只提交服务器明确要求的完整凭据;密码仅保留当前面板内存,不写入持久化存储。
|
|
if (!g || o.value !== `credentials` || u.value.some((t) => !e[t]))
|
|
return !1;
|
|
try {
|
|
return (
|
|
g.sendCredentials(e),
|
|
(o.value = `connecting`),
|
|
(u.value = []),
|
|
E(d),
|
|
!0
|
|
);
|
|
} catch {
|
|
return (w(`控制台验证失败,请重新连接。`), !1);
|
|
}
|
|
}
|
|
function A() {
|
|
if (o.value === `connected` && g)
|
|
try {
|
|
(g.sendCtrlAltDel(), g.focus());
|
|
} catch {
|
|
w(`连接已中断,请重新连接。`);
|
|
}
|
|
}
|
|
(watch(l, (e) => {
|
|
g && (g.scaleViewport = e);
|
|
}),
|
|
watch(
|
|
[n.visible, n.hostId, n.module, e],
|
|
() => {
|
|
n.visible() && e.value
|
|
? O()
|
|
: (S(), (o.value = `idle`), (c.value = ``));
|
|
},
|
|
{
|
|
flush: `post`,
|
|
immediate: !0,
|
|
},
|
|
),
|
|
watch(
|
|
() => r.token,
|
|
() => {
|
|
(S(), (o.value = `idle`), n.visible() && n.close());
|
|
},
|
|
{
|
|
flush: `sync`,
|
|
},
|
|
));
|
|
function j(e) {
|
|
// 其他标签页退出或更换账号时立即断开,不能等用户下一次远控操作才识别身份变化。
|
|
(e.key === `jwt` || e.key === null) &&
|
|
n.visible() &&
|
|
(S(), (o.value = `idle`), n.close());
|
|
}
|
|
return (
|
|
onMounted(() => window.addEventListener(`storage`, j)),
|
|
onBeforeUnmount(() => {
|
|
((f = !0), S(), window.removeEventListener(`storage`, j));
|
|
}),
|
|
{
|
|
state: o,
|
|
error: c,
|
|
fit: l,
|
|
credentialTypes: u,
|
|
connect: O,
|
|
disconnect: C,
|
|
submitCredentials: k,
|
|
sendCtrlAltDel: A,
|
|
}
|
|
);
|
|
}
|
|
var D = [`aria-labelledby`],
|
|
O = {
|
|
class: `console-header`,
|
|
},
|
|
k = {
|
|
class: `console-heading`,
|
|
},
|
|
A = [`id`],
|
|
j = {
|
|
class: `host-id`,
|
|
},
|
|
M = {
|
|
key: 0,
|
|
class: `console-target`,
|
|
},
|
|
ee = {
|
|
class: `console-toolbar`,
|
|
role: `toolbar`,
|
|
"aria-label": `远程控制台操作`,
|
|
},
|
|
te = {
|
|
class: `toolbar-group`,
|
|
},
|
|
ne = {
|
|
class: `toolbar-group`,
|
|
},
|
|
re = {
|
|
key: 0,
|
|
class: `toolbar-message`,
|
|
role: `status`,
|
|
},
|
|
ie = [`aria-busy`],
|
|
ae = [`aria-label`],
|
|
oe = {
|
|
key: 0,
|
|
class: `console-overlay`,
|
|
},
|
|
se = [`for`],
|
|
ce = [`for`],
|
|
N = [`for`],
|
|
P = {
|
|
key: 3,
|
|
class: `credential-error`,
|
|
role: `alert`,
|
|
},
|
|
F = {
|
|
key: 1,
|
|
class: `connection-message`,
|
|
role: `status`,
|
|
"aria-live": `polite`,
|
|
},
|
|
I = Object.assign(
|
|
_plugin_vue_export_helper_t(
|
|
defineComponent({
|
|
__name: `RemoteConsole`,
|
|
props: {
|
|
visible: {
|
|
type: Boolean,
|
|
},
|
|
hostId: {},
|
|
module: {},
|
|
hostName: {},
|
|
operatePassword: {},
|
|
},
|
|
emits: [`update:visible`],
|
|
setup(g, { emit: b }) {
|
|
// 面板状态负责凭据表单、全屏与显示文案,连接生命周期由上面的状态机统一管理。
|
|
let x = g,
|
|
C = b,
|
|
T = useId(),
|
|
I = ref(null),
|
|
L = ref(null),
|
|
R = ref(!1),
|
|
z = ref(``),
|
|
B = ref(``),
|
|
V = ref(``),
|
|
H = ref(``),
|
|
U = ref(``),
|
|
{
|
|
state: W,
|
|
error: le,
|
|
fit: G,
|
|
credentialTypes: K,
|
|
connect: q,
|
|
disconnect: J,
|
|
submitCredentials: ue,
|
|
sendCtrlAltDel: de,
|
|
} = E(I, {
|
|
visible: () => x.visible,
|
|
hostId: () => x.hostId,
|
|
module: () => x.module,
|
|
operatePassword: () => x.operatePassword,
|
|
close: () => C(`update:visible`, !1),
|
|
}),
|
|
Y = computed(
|
|
() => W.value === `creating` || W.value === `connecting`,
|
|
),
|
|
X = computed(
|
|
() =>
|
|
({
|
|
idle: `准备连接`,
|
|
creating: `正在建立会话`,
|
|
connecting: `正在连接`,
|
|
credentials: `等待验证`,
|
|
connected: `已连接`,
|
|
disconnected: `已断开`,
|
|
error: `连接失败`,
|
|
})[W.value],
|
|
),
|
|
Z = computed(() => x.hostName?.trim() || `服务器实例`);
|
|
function Q() {
|
|
// 状态或可见性变化就清除输入,避免旧会话的凭据留在重新打开的表单中。
|
|
((z.value = ``), (B.value = ``), (V.value = ``), (H.value = ``));
|
|
}
|
|
watch([W, () => x.visible], Q);
|
|
function fe() {
|
|
((H.value = ``),
|
|
ue({
|
|
password: z.value,
|
|
username: B.value,
|
|
target: V.value,
|
|
})
|
|
? Q()
|
|
: W.value === `credentials` &&
|
|
(H.value = `请填写所需的验证信息。`));
|
|
}
|
|
function pe() {
|
|
(J(), Q(), C(`update:visible`, !1));
|
|
}
|
|
async function me() {
|
|
// 全屏是浏览器交互能力;失败只显示提示,不影响现有远程连接。
|
|
U.value = ``;
|
|
try {
|
|
document.fullscreenElement === L.value
|
|
? await document.exitFullscreen()
|
|
: L.value?.requestFullscreen
|
|
? await L.value.requestFullscreen()
|
|
: (U.value = `当前浏览器不支持全屏,可使用浏览器缩放调整显示。`);
|
|
} catch {
|
|
U.value = `未能进入全屏,请重试。`;
|
|
}
|
|
}
|
|
function $() {
|
|
R.value = !!L.value && document.fullscreenElement === L.value;
|
|
}
|
|
return (
|
|
onMounted(() => document.addEventListener(`fullscreenchange`, $)),
|
|
onBeforeUnmount(() =>
|
|
document.removeEventListener(`fullscreenchange`, $),
|
|
),
|
|
(t, n) => {
|
|
let i = button,
|
|
a = inputtext;
|
|
return g.visible
|
|
? (openBlock(),
|
|
createElementBlock(
|
|
`section`,
|
|
{
|
|
key: 0,
|
|
ref_key: `surface`,
|
|
ref: L,
|
|
class: normalizeClass([
|
|
`remote-console`,
|
|
{
|
|
"is-fullscreen": unref(R),
|
|
},
|
|
]),
|
|
"aria-labelledby": `${unref(T)}-title`,
|
|
},
|
|
[
|
|
createElementVNode(`header`, O, [
|
|
(n[7] ||= createElementVNode(
|
|
`span`,
|
|
{
|
|
class: `console-mark`,
|
|
"aria-hidden": `true`,
|
|
},
|
|
[
|
|
createElementVNode(`i`, {
|
|
class: `pi pi-desktop`,
|
|
}),
|
|
],
|
|
-1,
|
|
)),
|
|
createElementVNode(`div`, k, [
|
|
(n[5] ||= createElementVNode(
|
|
`p`,
|
|
{
|
|
class: `console-brand`,
|
|
},
|
|
`破碎工坊云`,
|
|
-1,
|
|
)),
|
|
createElementVNode(
|
|
`h1`,
|
|
{
|
|
id: `${unref(T)}-title`,
|
|
},
|
|
[
|
|
(n[4] ||= createTextVNode(`远程控制台`, -1)),
|
|
createElementVNode(
|
|
`span`,
|
|
j,
|
|
`#` + toDisplayString(g.hostId),
|
|
1,
|
|
),
|
|
],
|
|
8,
|
|
A,
|
|
),
|
|
g.hostName
|
|
? (openBlock(),
|
|
createElementBlock(
|
|
`p`,
|
|
M,
|
|
toDisplayString(unref(Z)),
|
|
1,
|
|
))
|
|
: createCommentVNode(``, !0),
|
|
]),
|
|
createElementVNode(
|
|
`span`,
|
|
{
|
|
class: normalizeClass([
|
|
`connection-state`,
|
|
`state-${unref(W)}`,
|
|
]),
|
|
role: `status`,
|
|
"aria-live": `polite`,
|
|
},
|
|
[
|
|
(n[6] ||= createElementVNode(
|
|
`span`,
|
|
{
|
|
class: `state-dot`,
|
|
"aria-hidden": `true`,
|
|
},
|
|
null,
|
|
-1,
|
|
)),
|
|
createTextVNode(toDisplayString(unref(X)), 1),
|
|
],
|
|
2,
|
|
),
|
|
createVNode(i, {
|
|
icon: `pi pi-times`,
|
|
"aria-label": `关闭远程控制台`,
|
|
text: ``,
|
|
severity: `secondary`,
|
|
rounded: ``,
|
|
onClick: pe,
|
|
}),
|
|
]),
|
|
createElementVNode(`div`, ee, [
|
|
createElementVNode(`div`, te, [
|
|
createVNode(
|
|
i,
|
|
{
|
|
label: `适应窗口`,
|
|
icon: `pi pi-expand`,
|
|
outlined: !unref(G),
|
|
severity: unref(G) ? `primary` : `secondary`,
|
|
size: `small`,
|
|
"aria-pressed": unref(G),
|
|
onClick: (n[0] ||= (e) => (G.value = !unref(G))),
|
|
},
|
|
null,
|
|
8,
|
|
[`outlined`, `severity`, `aria-pressed`],
|
|
),
|
|
createVNode(
|
|
i,
|
|
{
|
|
label: unref(R) ? `退出全屏` : `全屏`,
|
|
icon: unref(R)
|
|
? `pi pi-window-minimize`
|
|
: `pi pi-window-maximize`,
|
|
outlined: ``,
|
|
severity: `secondary`,
|
|
size: `small`,
|
|
onClick: me,
|
|
},
|
|
null,
|
|
8,
|
|
[`label`, `icon`],
|
|
),
|
|
createVNode(
|
|
i,
|
|
{
|
|
label: `Ctrl + Alt + Del`,
|
|
outlined: ``,
|
|
severity: `secondary`,
|
|
size: `small`,
|
|
disabled: unref(W) !== `connected`,
|
|
onClick: unref(de),
|
|
},
|
|
null,
|
|
8,
|
|
[`disabled`, `onClick`],
|
|
),
|
|
]),
|
|
createElementVNode(`div`, ne, [
|
|
createVNode(
|
|
i,
|
|
{
|
|
label: `重新连接`,
|
|
icon: `pi pi-refresh`,
|
|
outlined: ``,
|
|
severity: `secondary`,
|
|
size: `small`,
|
|
disabled: unref(Y),
|
|
onClick: unref(q),
|
|
},
|
|
null,
|
|
8,
|
|
[`disabled`, `onClick`],
|
|
),
|
|
createVNode(
|
|
i,
|
|
{
|
|
label: `断开`,
|
|
icon: `pi pi-power-off`,
|
|
text: ``,
|
|
severity: `secondary`,
|
|
size: `small`,
|
|
disabled:
|
|
unref(W) === `idle` ||
|
|
unref(W) === `disconnected` ||
|
|
unref(W) === `error`,
|
|
onClick: unref(J),
|
|
},
|
|
null,
|
|
8,
|
|
[`disabled`, `onClick`],
|
|
),
|
|
]),
|
|
]),
|
|
unref(U)
|
|
? (openBlock(),
|
|
createElementBlock(
|
|
`p`,
|
|
re,
|
|
toDisplayString(unref(U)),
|
|
1,
|
|
))
|
|
: createCommentVNode(``, !0),
|
|
createElementVNode(
|
|
`div`,
|
|
{
|
|
class: `console-display`,
|
|
"aria-busy": unref(Y),
|
|
},
|
|
[
|
|
createElementVNode(
|
|
`div`,
|
|
{
|
|
ref_key: `screen`,
|
|
ref: I,
|
|
class: `console-screen`,
|
|
"aria-label": `${unref(Z)} 的远程屏幕`,
|
|
},
|
|
null,
|
|
8,
|
|
ae,
|
|
),
|
|
unref(W) === `connected`
|
|
? createCommentVNode(``, !0)
|
|
: (openBlock(),
|
|
createElementBlock(`div`, oe, [
|
|
unref(W) === `credentials`
|
|
? (openBlock(),
|
|
createElementBlock(
|
|
`form`,
|
|
{
|
|
key: 0,
|
|
class: `credential-form`,
|
|
onSubmit: withModifiers(fe, [
|
|
`prevent`,
|
|
]),
|
|
},
|
|
[
|
|
(n[8] ||= createElementVNode(
|
|
`i`,
|
|
{
|
|
class: `pi pi-lock state-icon`,
|
|
"aria-hidden": `true`,
|
|
},
|
|
null,
|
|
-1,
|
|
)),
|
|
(n[9] ||= createElementVNode(
|
|
`h3`,
|
|
null,
|
|
`验证控制台连接`,
|
|
-1,
|
|
)),
|
|
(n[10] ||= createElementVNode(
|
|
`p`,
|
|
null,
|
|
`请输入此控制台要求的连接凭据。`,
|
|
-1,
|
|
)),
|
|
unref(K).includes(`username`)
|
|
? (openBlock(),
|
|
createElementBlock(
|
|
Fragment,
|
|
{
|
|
key: 0,
|
|
},
|
|
[
|
|
createElementVNode(
|
|
`label`,
|
|
{
|
|
for: `${unref(T)}-username`,
|
|
},
|
|
`用户名`,
|
|
8,
|
|
se,
|
|
),
|
|
createVNode(
|
|
a,
|
|
{
|
|
id: `${unref(T)}-username`,
|
|
modelValue: unref(B),
|
|
"onUpdate:modelValue":
|
|
(n[1] ||= (e) =>
|
|
isRef(B)
|
|
? (B.value = e)
|
|
: null),
|
|
autocomplete: `off`,
|
|
fluid: ``,
|
|
},
|
|
null,
|
|
8,
|
|
[`id`, `modelValue`],
|
|
),
|
|
],
|
|
64,
|
|
))
|
|
: createCommentVNode(``, !0),
|
|
unref(K).includes(`target`)
|
|
? (openBlock(),
|
|
createElementBlock(
|
|
Fragment,
|
|
{
|
|
key: 1,
|
|
},
|
|
[
|
|
createElementVNode(
|
|
`label`,
|
|
{
|
|
for: `${unref(T)}-target`,
|
|
},
|
|
`目标`,
|
|
8,
|
|
ce,
|
|
),
|
|
createVNode(
|
|
a,
|
|
{
|
|
id: `${unref(T)}-target`,
|
|
modelValue: unref(V),
|
|
"onUpdate:modelValue":
|
|
(n[2] ||= (e) =>
|
|
isRef(V)
|
|
? (V.value = e)
|
|
: null),
|
|
autocomplete: `off`,
|
|
fluid: ``,
|
|
},
|
|
null,
|
|
8,
|
|
[`id`, `modelValue`],
|
|
),
|
|
],
|
|
64,
|
|
))
|
|
: createCommentVNode(``, !0),
|
|
unref(K).includes(`password`)
|
|
? (openBlock(),
|
|
createElementBlock(
|
|
Fragment,
|
|
{
|
|
key: 2,
|
|
},
|
|
[
|
|
createElementVNode(
|
|
`label`,
|
|
{
|
|
for: `${unref(T)}-password`,
|
|
},
|
|
`控制台密码`,
|
|
8,
|
|
N,
|
|
),
|
|
createVNode(
|
|
a,
|
|
{
|
|
id: `${unref(T)}-password`,
|
|
modelValue: unref(z),
|
|
"onUpdate:modelValue":
|
|
(n[3] ||= (e) =>
|
|
isRef(z)
|
|
? (z.value = e)
|
|
: null),
|
|
type: `password`,
|
|
autocomplete: `off`,
|
|
fluid: ``,
|
|
},
|
|
null,
|
|
8,
|
|
[`id`, `modelValue`],
|
|
),
|
|
],
|
|
64,
|
|
))
|
|
: createCommentVNode(``, !0),
|
|
unref(H)
|
|
? (openBlock(),
|
|
createElementBlock(
|
|
`p`,
|
|
P,
|
|
toDisplayString(unref(H)),
|
|
1,
|
|
))
|
|
: createCommentVNode(``, !0),
|
|
createVNode(i, {
|
|
type: `submit`,
|
|
label: `连接`,
|
|
fluid: ``,
|
|
}),
|
|
],
|
|
32,
|
|
))
|
|
: (openBlock(),
|
|
createElementBlock(`div`, F, [
|
|
createElementVNode(
|
|
`i`,
|
|
{
|
|
class: normalizeClass([
|
|
unref(Y)
|
|
? `pi pi-spinner pi-spin`
|
|
: unref(W) === `error`
|
|
? `pi pi-exclamation-circle`
|
|
: `pi pi-desktop`,
|
|
`state-icon`,
|
|
]),
|
|
"aria-hidden": `true`,
|
|
},
|
|
null,
|
|
2,
|
|
),
|
|
createElementVNode(
|
|
`h3`,
|
|
null,
|
|
toDisplayString(unref(X)),
|
|
1,
|
|
),
|
|
createElementVNode(
|
|
`p`,
|
|
null,
|
|
toDisplayString(
|
|
unref(le) ||
|
|
(unref(Y)
|
|
? `连接启动可能需要一些时间,请稍候。`
|
|
: unref(W) === `disconnected`
|
|
? `远程会话已结束,实例继续运行。`
|
|
: `正在准备您的远程屏幕。`),
|
|
),
|
|
1,
|
|
),
|
|
unref(W) === `error` ||
|
|
unref(W) === `disconnected`
|
|
? (openBlock(),
|
|
createBlock(
|
|
i,
|
|
{
|
|
key: 0,
|
|
label: `重新连接`,
|
|
icon: `pi pi-refresh`,
|
|
onClick: unref(q),
|
|
},
|
|
null,
|
|
8,
|
|
[`onClick`],
|
|
))
|
|
: createCommentVNode(``, !0),
|
|
])),
|
|
])),
|
|
],
|
|
8,
|
|
ie,
|
|
),
|
|
(n[11] ||= createElementVNode(
|
|
`footer`,
|
|
{
|
|
class: `console-footer`,
|
|
},
|
|
[
|
|
createElementVNode(
|
|
`span`,
|
|
null,
|
|
`点击远程屏幕后使用键盘与鼠标操作。`,
|
|
),
|
|
createElementVNode(
|
|
`span`,
|
|
null,
|
|
`关闭控制台不会关闭实例`,
|
|
),
|
|
],
|
|
-1,
|
|
)),
|
|
],
|
|
10,
|
|
D,
|
|
))
|
|
: createCommentVNode(``, !0);
|
|
}
|
|
);
|
|
},
|
|
}),
|
|
[[`__scopeId`, `data-v-e696489e`]],
|
|
),
|
|
{
|
|
__name: `RemoteConsole`,
|
|
},
|
|
);
|
|
export {};
|
|
export default I;
|
|
</script>
|