Удаление файла
This commit is contained in:
@@ -1,86 +0,0 @@
|
|||||||
// VNC-консоль через noVNC.
|
|
||||||
//
|
|
||||||
// В noVNC 1.4.0 основной модуль — это ES-модуль (core/rfb.js), который
|
|
||||||
// экспортирует класс RFB через `export default`. Грузим его через
|
|
||||||
// динамический import(). Скрипт и его зависимости (vendor/, utils/,
|
|
||||||
// core/inflator.js и т.п.) лежат в /novnc/* внутри nginx-контейнера —
|
|
||||||
// собирается в Docker-образе из GitHub release (см. frontend/Dockerfile).
|
|
||||||
|
|
||||||
import { useEffect, useRef, useState } from "react";
|
|
||||||
import { api } from "../api.js";
|
|
||||||
|
|
||||||
// @vite-ignore — запрещаем Vite пытаться разрешить путь на этапе сборки,
|
|
||||||
// иначе он упадёт, не найдя модуль в локальной файловой системе.
|
|
||||||
const NOVNC_MODULE_URL = "/novnc/core/rfb.js";
|
|
||||||
|
|
||||||
let modulePromise = null;
|
|
||||||
|
|
||||||
function loadNoVNC() {
|
|
||||||
if (modulePromise) return modulePromise;
|
|
||||||
modulePromise = import(/* @vite-ignore */ NOVNC_MODULE_URL)
|
|
||||||
.then((mod) => {
|
|
||||||
if (!mod.default) {
|
|
||||||
throw new Error("RFB не найден в модуле noVNC");
|
|
||||||
}
|
|
||||||
return mod.default;
|
|
||||||
});
|
|
||||||
return modulePromise;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function ConsoleViewer({ instanceId }) {
|
|
||||||
const containerRef = useRef(null);
|
|
||||||
const rfbRef = useRef(null);
|
|
||||||
const [status, setStatus] = useState("Подключение…");
|
|
||||||
const [error, setError] = useState("");
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
let cancelled = false;
|
|
||||||
|
|
||||||
async function connect() {
|
|
||||||
try {
|
|
||||||
const info = await api.getConsole(instanceId);
|
|
||||||
const RFB = await loadNoVNC();
|
|
||||||
if (cancelled) return;
|
|
||||||
|
|
||||||
const proto = window.location.protocol === "https:" ? "wss" : "ws";
|
|
||||||
const wsUrl =
|
|
||||||
`${proto}://${window.location.host}/api/console/ws?` +
|
|
||||||
`node=${encodeURIComponent(info.node)}` +
|
|
||||||
`&vmid=${info.vmid}` +
|
|
||||||
`&guest_type=${info.guest_type}` +
|
|
||||||
`&port=${info.port}` +
|
|
||||||
`&ticket=${encodeURIComponent(info.ticket)}`;
|
|
||||||
|
|
||||||
const rfb = new RFB(containerRef.current, wsUrl);
|
|
||||||
rfb.addEventListener("connect", () => !cancelled && setStatus("Подключено"));
|
|
||||||
rfb.addEventListener("disconnect", () => !cancelled && setStatus("Соединение закрыто"));
|
|
||||||
rfbRef.current = rfb;
|
|
||||||
} catch (err) {
|
|
||||||
if (!cancelled) setError(err.message || String(err));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
connect();
|
|
||||||
return () => {
|
|
||||||
cancelled = true;
|
|
||||||
if (rfbRef.current && typeof rfbRef.current.disconnect === "function") {
|
|
||||||
try { rfbRef.current.disconnect(); } catch { /* noop */ }
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}, [instanceId]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<div className="status-row" style={{ marginBottom: 8 }}>
|
|
||||||
<span className={`dot ${error ? "error" : "running"}`} /> {error ? "Ошибка консоли" : status}
|
|
||||||
</div>
|
|
||||||
{error && (
|
|
||||||
<div className="error-box">
|
|
||||||
{error}. Консоль VNC зависит от версии Proxmox и настроек аутентификации — см. README, раздел
|
|
||||||
«Консоль VNC».
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
<div className="console-frame" ref={containerRef} style={{ width: "100%", height: 480 }} />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user