docs: annotate payment, host operations and shared components

This commit is contained in:
cieanyau committed 2026-11-06 00:29:13 +08:00
1 parent d37ce57d09
commit dc32a74d7a
17 files changed
+100

No files matched your search

+18
View File
@@ -1,4 +1,9 @@
<script>
/**
* 同源远程控制台:父级提供实例、模块及操作密码,通过 update:visible 关闭面板。
* 浏览器只向 /remote-console/sessions 申请短期会话,再以服务端返回的同源路径连接 noVNC。
* 这里不直连供应商 VNC 地址;部署时 HTTP 与 WebSocket 路径都需要网关反向代理。
*/
import "~/assets/styles/RemoteConsole.DLmX5UZu.css";
import { toDisplayString } from "vue";
import { onMounted } from "vue";
@@ -27,6 +32,7 @@ import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helpe
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(``),
@@ -43,6 +49,7 @@ function E(e, n) {
(m !== null && clearTimeout(m), (m = null));
}
async function y(e, t) {
// 使用创建会话时的 token 做尽力释放;keepalive 允许页面离开时仍发送清理请求。
if (T.test(e))
try {
await fetch(`/remote-console/sessions/${e}`, {
@@ -57,6 +64,7 @@ function E(e, n) {
} catch {}
}
function S() {
// 统一释放入口先推进代次,再中止请求、断开 RFB、移除事件并删除远端会话。
if ((d++, p?.abort(), (p = null), v(), g)) {
for (let [e, t] of _) g.removeEventListener(e, t);
try {
@@ -76,12 +84,14 @@ function E(e, n) {
(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;
@@ -91,6 +101,7 @@ function E(e, n) {
: `控制台暂时无法连接,请稍后重试。`;
}
async function O() {
// 登录状态、实例、模块和挂载节点共同构成连接身份;异步阶段每次回写前都重新核对。
if ((S(), (c.value = ``), f || !n.visible() || !e.value)) {
o.value = `idle`;
return;
@@ -146,6 +157,7 @@ function E(e, n) {
? r.sessionId
: ``;
if (!x()) {
// 创建成功但用户已关闭或切换实例时,仍要回收刚生成的服务端会话。
d && y(d, t);
return;
}
@@ -165,6 +177,7 @@ function E(e, n) {
return;
}
let { default: f } = await loadModule(
// 只在实际连接时加载 noVNC,避免把远控依赖放进所有页面的首屏执行路径。
async () => {
let { default: e } = await import("@novnc/novnc");
return {
@@ -226,6 +239,7 @@ function E(e, n) {
}
}
function k(e) {
// 只提交服务器明确要求的完整凭据;密码仅保留当前面板内存,不写入持久化存储。
if (!g || o.value !== `credentials` || u.value.some((t) => !e[t]))
return !1;
try {
@@ -273,6 +287,7 @@ function E(e, n) {
},
));
function j(e) {
// 其他标签页退出或更换账号时立即断开,不能等用户下一次远控操作才识别身份变化。
(e.key === `jwt` || e.key === null) &&
n.visible() &&
(S(), (o.value = `idle`), n.close());
@@ -360,6 +375,7 @@ var D = [`aria-labelledby`],
},
emits: [`update:visible`],
setup(g, { emit: b }) {
// 面板状态负责凭据表单、全屏与显示文案,连接生命周期由上面的状态机统一管理。
let x = g,
C = b,
T = useId(),
@@ -404,6 +420,7 @@ var D = [`aria-labelledby`],
),
Z = computed(() => x.hostName?.trim() || `服务器实例`);
function Q() {
// 状态或可见性变化就清除输入,避免旧会话的凭据留在重新打开的表单中。
((z.value = ``), (B.value = ``), (V.value = ``), (H.value = ``));
}
watch([W, () => x.visible], Q);
@@ -422,6 +439,7 @@ var D = [`aria-labelledby`],
(J(), Q(), C(`update:visible`, !1));
}
async function me() {
// 全屏是浏览器交互能力;失败只显示提示,不影响现有远程连接。
U.value = ``;
try {
document.fullscreenElement === L.value