device-center 0.2.0-beta.2 → 0.2.0-beta.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CONTRIBUTING.md +2 -0
- package/Dockerfile +2 -1
- package/README.md +23 -4
- package/bin/device-center.mjs +3 -2
- package/docs/agent-install.md +41 -7
- package/docs/driver-binding.md +11 -1
- package/docs/friend-trial.md +2 -2
- package/docs/hosted-access.md +1 -1
- package/docs/i18n.md +32 -0
- package/docs/npm.md +9 -7
- package/docs/onboarding.md +3 -1
- package/docs/remote-access.md +2 -2
- package/docs/roadmap.md +6 -0
- package/docs/security-and-sync.md +2 -0
- package/favicon.svg +4 -0
- package/index.html +2 -0
- package/login.html +2 -2
- package/npm-shrinkwrap.json +2 -2
- package/package.json +4 -2
- package/scripts/driver.mjs +27 -10
- package/server/cloudAccess.mjs +7 -1
- package/server/drivers/browserPairing.mjs +41 -0
- package/server/drivers/cloudRegistry.mjs +23 -6
- package/server/index.mjs +5 -2
- package/src/api.js +4 -1
- package/src/device-state.js +13 -12
- package/src/i18n.css +61 -0
- package/src/i18n.js +174 -0
- package/src/install-prompt.js +19 -0
- package/src/install-walkthrough.js +49 -0
- package/src/login.js +20 -11
- package/src/main.js +137 -124
- package/src/messages.js +7365 -0
- package/src/onboarding.js +41 -13
- package/src/pair.css +23 -0
- package/src/pair.js +60 -0
- package/src/pairing-handoff.js +30 -0
- package/src/start.css +265 -45
- package/src/start.js +153 -16
- package/src/styles.css +1 -1
- package/start.html +138 -29
package/src/start.js
CHANGED
|
@@ -1,23 +1,160 @@
|
|
|
1
|
-
import { agentInstallPrompt } from './onboarding.js';
|
|
1
|
+
import { agentInstallPrompt, agentInstallPlan, terminalInstallScript, OFFICIAL_CONTROL_ORIGIN } from './onboarding.js';
|
|
2
|
+
import { initLanguage, getLocale, t } from './i18n.js';
|
|
3
|
+
import { installWalkthroughMarkup } from './install-walkthrough.js';
|
|
2
4
|
|
|
3
5
|
const text = document.querySelector('#install-instructions');
|
|
4
6
|
const result = document.querySelector('#copy-result');
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
7
|
+
const customOrigin = document.querySelector('#custom-origin');
|
|
8
|
+
// Shared links only preselect UI choices; strict plan validation still gates copying.
|
|
9
|
+
const guideParams = new URLSearchParams(location.search);
|
|
10
|
+
let mode = ['local', 'official', 'self-hosted'].includes(guideParams.get('mode')) ? guideParams.get('mode') : 'local';
|
|
11
|
+
let method = guideParams.get('method') === 'manual' ? 'manual' : 'agent';
|
|
12
|
+
let pairingMethod = 'browser';
|
|
13
|
+
customOrigin.value = mode === 'self-hosted' ? guideParams.get('origin') ?? '' : '';
|
|
14
|
+
for (const input of document.querySelectorAll('input[name="install-mode"]')) input.checked = input.value === mode;
|
|
15
|
+
for (const input of document.querySelectorAll('input[name="install-method"]')) input.checked = input.value === method;
|
|
16
|
+
if (mode === 'self-hosted') document.querySelector('.custom').open = true;
|
|
17
|
+
const scene = document.querySelector('.scene');
|
|
18
|
+
const motionToggle = document.querySelector('.motion-toggle');
|
|
19
|
+
motionToggle.addEventListener('click', () => {
|
|
20
|
+
const paused = scene.dataset.paused !== 'true';
|
|
21
|
+
scene.dataset.paused = String(paused);
|
|
22
|
+
const key = paused ? 'guide.visual.playMotion' : 'guide.visual.pauseMotion';
|
|
23
|
+
motionToggle.dataset.i18nAriaLabel = key;
|
|
24
|
+
motionToggle.dataset.i18nTitle = key;
|
|
25
|
+
motionToggle.setAttribute('aria-label', t(key));
|
|
26
|
+
motionToggle.setAttribute('title', t(key));
|
|
27
|
+
});
|
|
28
|
+
let sceneFrame = null;
|
|
29
|
+
scene.addEventListener('pointermove', event => {
|
|
30
|
+
if (event.pointerType !== 'mouse' || scene.dataset.paused === 'true' || matchMedia('(prefers-reduced-motion: reduce)').matches) return;
|
|
31
|
+
if (sceneFrame !== null) cancelAnimationFrame(sceneFrame);
|
|
32
|
+
const box = scene.getBoundingClientRect();
|
|
33
|
+
const x = (event.clientX - box.left) / box.width - .5;
|
|
34
|
+
const y = (event.clientY - box.top) / box.height - .5;
|
|
35
|
+
sceneFrame = requestAnimationFrame(() => {
|
|
36
|
+
scene.style.setProperty('--scene-rx', `${-y * 4}deg`);
|
|
37
|
+
scene.style.setProperty('--scene-ry', `${x * 6}deg`);
|
|
38
|
+
sceneFrame = null;
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
scene.addEventListener('pointerleave', () => {
|
|
42
|
+
if (sceneFrame !== null) cancelAnimationFrame(sceneFrame);
|
|
43
|
+
sceneFrame = null;
|
|
44
|
+
scene.style.setProperty('--scene-rx', '0deg');
|
|
45
|
+
scene.style.setProperty('--scene-ry', '0deg');
|
|
46
|
+
});
|
|
47
|
+
const copyButton = document.querySelector('#copy-instructions');
|
|
48
|
+
const nextAction = document.querySelector('#next-action');
|
|
49
|
+
let copied = false;
|
|
50
|
+
let copyGeneration = 0;
|
|
51
|
+
let instructionsValid = false;
|
|
52
|
+
let walkthroughStep = 0;
|
|
53
|
+
function translatedText(selector, key) {
|
|
54
|
+
const element = document.querySelector(selector);
|
|
55
|
+
element.dataset.i18n = key;
|
|
56
|
+
element.textContent = t(key);
|
|
57
|
+
}
|
|
58
|
+
function updateGuidance() {
|
|
59
|
+
const manual = method === 'manual';
|
|
60
|
+
translatedText('#copy-label', manual ? 'guide.manual.copy' : { local: 'guide.localCopy', official: 'guide.hostedCopy', 'self-hosted': 'guide.customCopy' }[mode]);
|
|
61
|
+
translatedText('#copy-hint', manual ? 'guide.manual.copyHint' : 'guide.focus.copyHint');
|
|
62
|
+
translatedText('#instruction-preview', manual ? 'guide.manual.preview' : 'guide.preview');
|
|
63
|
+
const fieldLabel = manual ? 'guide.manual.scriptLabel' : 'guide.instructions';
|
|
64
|
+
text.dataset.i18nAriaLabel = fieldLabel;
|
|
65
|
+
text.setAttribute('aria-label', t(fieldLabel));
|
|
66
|
+
document.querySelector('#manual-options').hidden = !manual;
|
|
67
|
+
document.querySelector('#pairing-options').hidden = !manual || mode === 'local';
|
|
68
|
+
translatedText('[data-hosted-dashboard]', walkthroughStep === 2 ? 'walk.openDevices' : 'guide.manual.openPanel');
|
|
69
|
+
nextAction.dataset.copied = String(copied);
|
|
70
|
+
}
|
|
71
|
+
const errorKey = error => error.translationKey ?? 'error.custom';
|
|
72
|
+
function refreshInstructions() {
|
|
73
|
+
const options = { locale: getLocale(), mode, ...(mode === 'self-hosted' ? { origin: customOrigin.value.trim() } : {}) };
|
|
74
|
+
const link = document.querySelector('[data-hosted-dashboard]');
|
|
75
|
+
document.querySelector('#custom-fields').hidden = mode !== 'self-hosted';
|
|
76
|
+
updateGuidance();
|
|
77
|
+
let plan;
|
|
78
|
+
try {
|
|
79
|
+
plan = agentInstallPlan(options);
|
|
80
|
+
text.value = method === 'manual' ? terminalInstallScript({ ...options, browser: pairingMethod === 'browser' }) : agentInstallPrompt(options);
|
|
81
|
+
instructionsValid = true;
|
|
82
|
+
customOrigin.removeAttribute('aria-invalid');
|
|
83
|
+
const url = new URL('/login', plan.controlOrigin ?? OFFICIAL_CONTROL_ORIGIN);
|
|
84
|
+
url.searchParams.set('lang', getLocale());
|
|
85
|
+
link.href = url.href;
|
|
86
|
+
link.hidden = mode === 'local' || !copied || (walkthroughStep !== 2 && !(walkthroughStep === 1 && method === 'manual' && pairingMethod === 'headless'));
|
|
87
|
+
} catch (error) {
|
|
88
|
+
instructionsValid = false;
|
|
89
|
+
text.value = '';
|
|
90
|
+
link.hidden = true;
|
|
91
|
+
if (mode === 'self-hosted') customOrigin.setAttribute('aria-invalid', 'true');
|
|
92
|
+
result.textContent = t(errorKey(error));
|
|
93
|
+
result.className = 'error';
|
|
94
|
+
}
|
|
95
|
+
document.querySelector('#install-walkthrough').innerHTML = installWalkthroughMarkup({ method, mode, pairingMethod, step: walkthroughStep, copied, controlOrigin: plan?.controlOrigin, localUrl: plan?.url, locale: getLocale() });
|
|
96
|
+
copyButton.disabled = !instructionsValid;
|
|
97
|
+
}
|
|
98
|
+
function resetCopyState(resetStep = true) {
|
|
99
|
+
copyGeneration++;
|
|
100
|
+
copied = false;
|
|
101
|
+
if (resetStep) walkthroughStep = 0;
|
|
102
|
+
result.textContent = '';
|
|
103
|
+
result.className = '';
|
|
104
|
+
refreshInstructions();
|
|
105
|
+
}
|
|
106
|
+
initLanguage({ onChange: () => resetCopyState(false) });
|
|
107
|
+
document.querySelector('#install-walkthrough').addEventListener('click', event => {
|
|
108
|
+
const button = event.target.closest('[data-walk-step]');
|
|
8
109
|
if (!button || button.disabled) return;
|
|
9
|
-
const
|
|
110
|
+
const step = Number(button.dataset.walkStep);
|
|
111
|
+
if (!Number.isInteger(step) || step < 0 || step > 2) return;
|
|
112
|
+
walkthroughStep = step;
|
|
113
|
+
refreshInstructions();
|
|
114
|
+
nextAction.scrollIntoView({ block: 'start', behavior: matchMedia('(prefers-reduced-motion: reduce)').matches ? 'auto' : 'smooth' });
|
|
115
|
+
document.querySelector(`[data-walk-step="${walkthroughStep}"][aria-current="step"]`)?.focus({ preventScroll: true });
|
|
116
|
+
});
|
|
117
|
+
document.querySelector('.mode-options').addEventListener('change', event => {
|
|
118
|
+
if (!event.target.matches('input[name="install-mode"]')) return;
|
|
119
|
+
mode = event.target.value;
|
|
120
|
+
resetCopyState();
|
|
121
|
+
});
|
|
122
|
+
document.querySelector('.method-options').addEventListener('change', event => {
|
|
123
|
+
if (!event.target.matches('input[name="install-method"]')) return;
|
|
124
|
+
method = event.target.value;
|
|
125
|
+
resetCopyState();
|
|
126
|
+
});
|
|
127
|
+
document.querySelector('#pairing-options').addEventListener('change', event => {
|
|
128
|
+
if (!event.target.matches('input[name="pairing-method"]')) return;
|
|
129
|
+
pairingMethod = event.target.value;
|
|
130
|
+
resetCopyState();
|
|
131
|
+
});
|
|
132
|
+
customOrigin.addEventListener('input', () => {
|
|
133
|
+
if (mode === 'self-hosted') resetCopyState();
|
|
134
|
+
});
|
|
135
|
+
copyButton.addEventListener('click', async () => {
|
|
136
|
+
if (!instructionsValid || copyButton.disabled) return;
|
|
137
|
+
const generation = ++copyGeneration;
|
|
138
|
+
const prompt = text.value;
|
|
139
|
+
copyButton.disabled = true;
|
|
140
|
+
let success = false;
|
|
10
141
|
try {
|
|
11
|
-
|
|
12
|
-
} catch
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
try {
|
|
142
|
+
if (navigator.clipboard?.writeText) { await navigator.clipboard.writeText(prompt); success = true; }
|
|
143
|
+
} catch { /* Keep manual copy available. */ }
|
|
144
|
+
// Any changed installation choice invalidates this asynchronous result.
|
|
145
|
+
if (generation !== copyGeneration) return;
|
|
146
|
+
if (!success) {
|
|
147
|
+
document.querySelector('#instruction-details').open = true;
|
|
148
|
+
text.focus(); text.select();
|
|
149
|
+
try { success = document.execCommand('copy'); } catch { /* Selection is the fallback. */ }
|
|
150
|
+
}
|
|
151
|
+
copied = success;
|
|
152
|
+
if (success) walkthroughStep = 0;
|
|
153
|
+
result.className = success ? 'success' : '';
|
|
154
|
+
result.textContent = t(success ? method === 'manual' ? 'guide.manual.copied' : 'guide.focus.copied' : 'guide.manual');
|
|
155
|
+
refreshInstructions();
|
|
156
|
+
if (success) {
|
|
157
|
+
nextAction.scrollIntoView({ block: 'nearest', behavior: matchMedia('(prefers-reduced-motion: reduce)').matches ? 'auto' : 'smooth' });
|
|
158
|
+
document.querySelector('#walkthrough-title').focus({ preventScroll: true });
|
|
19
159
|
}
|
|
20
|
-
result.className = copied ? 'success' : '';
|
|
21
|
-
result.textContent = copied ? '已复制。粘贴给本机 Agent;托管绑定时由你登录并核对。' : '请手动复制下方已选中的完整说明。';
|
|
22
|
-
button.disabled = false;
|
|
23
160
|
});
|
package/src/styles.css
CHANGED
|
@@ -8,7 +8,7 @@ button:disabled { opacity: .55; cursor: wait; }
|
|
|
8
8
|
button:focus-visible, input:focus-visible, textarea:focus-visible, summary:focus-visible, a:focus-visible { outline: 3px solid #b5d7bf; outline-offset: 3px; }
|
|
9
9
|
.app-shell { height: 100vh; height: 100dvh; display: grid; grid-template-columns: 192px minmax(0, 1fr); overflow: hidden; }
|
|
10
10
|
.sidebar { min-height: 0; padding: 20px 14px; background: #fff; border-right: 1px solid var(--line); display: flex; flex-direction: column; overflow: auto; overscroll-behavior: contain; }
|
|
11
|
-
.sidebar
|
|
11
|
+
.sidebar .project-navigation { min-height: 0; flex: 1; overflow: auto; }
|
|
12
12
|
.brand { color: inherit; text-decoration: none; display: flex; align-items: center; gap: 10px; }
|
|
13
13
|
.brand-mark { width: 34px; height: 34px; flex: 0 0 auto; display: grid; place-items: center; color: white; background: #377c57; border-radius: 10px; }
|
|
14
14
|
.brand strong { display: block; font-size: 13px; }
|
package/start.html
CHANGED
|
@@ -3,43 +3,152 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
6
|
-
<meta name="description" content="
|
|
7
|
-
<title>开始试用 · Device Center</title>
|
|
6
|
+
<meta name="description" data-i18n-content="guide.visual.lead" content="让本机 Agent 查看其他设备的状态与授权日志。">
|
|
7
|
+
<title data-i18n="guide.title">开始试用 · Device Center</title>
|
|
8
|
+
<link rel="icon" href="/favicon.svg" type="image/svg+xml">
|
|
8
9
|
<link rel="stylesheet" href="/src/start.css">
|
|
10
|
+
<link rel="stylesheet" href="/src/i18n.css">
|
|
9
11
|
</head>
|
|
10
|
-
<body>
|
|
11
|
-
<
|
|
12
|
+
<body class="start-page">
|
|
13
|
+
<svg class="icon-library" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"><defs>
|
|
14
|
+
<symbol id="icon-copy" viewBox="0 0 24 24"><rect x="8" y="8" width="12" height="13" rx="2"/><path d="M16 8V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h3"/></symbol>
|
|
15
|
+
<symbol id="icon-computer" viewBox="0 0 24 24"><rect x="3" y="3" width="18" height="13" rx="2"/><path d="M8 21h8m-4-5v5M7 8l3 2-3 2m6 0h4"/></symbol>
|
|
16
|
+
<symbol id="icon-cloud" viewBox="0 0 24 24"><path d="M6 18h12a4 4 0 0 0 .5-8A6.5 6.5 0 0 0 6 8.5 4.8 4.8 0 0 0 6 18Z"/><path d="m9 12 3-3 3 3m-3-3v6"/></symbol>
|
|
17
|
+
<symbol id="icon-shield" viewBox="0 0 24 24"><path d="m12 3 8 3v6c0 4-5 7-8 9-3-2-8-5-8-9V6Z"/><path d="m8 12 3 3 5-6"/></symbol>
|
|
18
|
+
<symbol id="icon-log" viewBox="0 0 24 24"><rect x="5" y="3" width="14" height="18" rx="2"/><path d="M9 8h6m-6 4h6m-6 4h3"/></symbol>
|
|
19
|
+
<symbol id="icon-memory" viewBox="0 0 24 24"><rect x="5" y="5" width="14" height="14" rx="2"/><path d="M9 9h6v6H9ZM9 2v3m6-3v3M9 19v3m6-3v3M2 9h3m-3 6h3m14-6h3m-3 6h3"/></symbol>
|
|
20
|
+
<symbol id="icon-disk" viewBox="0 0 24 24"><rect x="3" y="4" width="18" height="16" rx="3"/><path d="M3 14h18m-5 3h1m-10 0h1"/></symbol>
|
|
21
|
+
<symbol id="icon-arrow" viewBox="0 0 24 24"><path d="M4 12h16m-6-6 6 6-6 6"/></symbol>
|
|
22
|
+
</defs></svg>
|
|
23
|
+
<header>
|
|
24
|
+
<a class="brand" href="/start" data-language-link><span class="brand-mark" aria-hidden="true"><svg viewBox="0 0 32 32"><path d="M4 22V5h17v17H4Zm7 5h17V10H11v17Z"/></svg></span><span>Device Center</span></a>
|
|
25
|
+
<div class="header-actions"><div class="language-picker" data-language-picker></div><span class="returning-user" data-i18n="guide.focus.alreadyInstalled">已接入?</span><a class="panel-link" href="/" data-language-link data-i18n-aria-label="guide.open" aria-label="进入设备面板"><span data-i18n="guide.visual.dashboard">设备面板</span><svg class="icon" aria-hidden="true"><use href="#icon-arrow"/></svg></a></div>
|
|
26
|
+
</header>
|
|
12
27
|
<main>
|
|
13
|
-
<section class="hero">
|
|
14
|
-
<
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
<div class="choices">
|
|
22
|
-
<article><h3>本机使用</h3><p>本机面板和 MCP,无需账号。适合先了解自己的电脑与已有设备资源。</p><button data-mode="local">复制本机安装说明</button></article>
|
|
23
|
-
<article><h3>官方托管</h3><p>用自己的账号管理设备,使用官方加密中转。Driver 和私钥仍留在设备上。</p><button class="primary" data-mode="official">复制托管安装说明</button></article>
|
|
28
|
+
<section class="hero" aria-labelledby="hero-title">
|
|
29
|
+
<div class="hero-copy">
|
|
30
|
+
<p class="eyebrow"><span class="section-index" data-i18n="guide.focus.overview">产品介绍</span><span data-i18n="guide.visual.yourDevices">用好你自己的设备</span></p>
|
|
31
|
+
<h1 id="hero-title"><span data-i18n="guide.visual.heroLine1">少切电脑。</span><span data-i18n="guide.visual.heroLine2">少搬日志。</span></h1>
|
|
32
|
+
<p class="lead" data-i18n="guide.visual.lead">让本机 Agent 查看其他设备的状态与授权日志。</p>
|
|
33
|
+
<div class="hero-actions"><a class="button primary hero-cta" href="#install-title"><span data-i18n="guide.visual.begin">开始接入</span><svg class="icon" aria-hidden="true"><use href="#icon-arrow"/></svg></a><span class="cta-hint" data-i18n="guide.focus.firstTry">第一次用?先选本机,无需账号。</span></div>
|
|
34
|
+
<p class="platform" data-i18n="guide.platform">macOS / Linux · Node.js 24+ · Windows 原生版暂未支持</p>
|
|
35
|
+
<p class="release-note"><span class="release-dot" aria-hidden="true"></span><span data-i18n="guide.badge">开发预览 · 0.2.0-beta.4 · MIT</span></p>
|
|
24
36
|
</div>
|
|
25
|
-
<
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
37
|
+
<figure class="scene" data-paused="false">
|
|
38
|
+
<figcaption class="scene-caption"><span><span class="caption-cross" aria-hidden="true">+</span><span data-i18n="guide.focus.example">工作原理示意 · 无需操作</span></span><button class="motion-toggle" type="button" data-i18n-aria-label="guide.visual.pauseMotion" data-i18n-title="guide.visual.pauseMotion" aria-label="暂停动效" title="暂停动效"><svg class="icon pause-icon" aria-hidden="true" viewBox="0 0 24 24"><path d="M8 5v14M16 5v14"/></svg><svg class="icon play-icon" aria-hidden="true" viewBox="0 0 24 24"><path d="m8 5 11 7-11 7Z"/></svg></button></figcaption>
|
|
39
|
+
<div class="scene-stage"><svg class="hardware-art" viewBox="0 0 640 510" aria-hidden="true" xmlns="http://www.w3.org/2000/svg">
|
|
40
|
+
<defs>
|
|
41
|
+
<linearGradient id="metal-top" x1="0" y1="0" x2="1" y2="1"><stop stop-color="#939395"/><stop offset=".18" stop-color="#505054"/><stop offset=".7" stop-color="#37373b"/><stop offset="1" stop-color="#747478"/></linearGradient>
|
|
42
|
+
<linearGradient id="metal-left" x1="0" y1="0" x2="0" y2="1"><stop stop-color="#39393d"/><stop offset=".3" stop-color="#232326"/><stop offset="1" stop-color="#111113"/></linearGradient>
|
|
43
|
+
<linearGradient id="metal-right" x1="0" y1="0" x2="1" y2="1"><stop stop-color="#1a1a1d"/><stop offset="1" stop-color="#080809"/></linearGradient>
|
|
44
|
+
<linearGradient id="copper-top" x1="0" y1="0" x2="1" y2="1"><stop stop-color="#ffab76"/><stop offset=".45" stop-color="#f5773b"/><stop offset="1" stop-color="#bd4e27"/></linearGradient>
|
|
45
|
+
<radialGradient id="floor-fade"><stop stop-color="white"/><stop offset=".75" stop-color="#666"/><stop offset="1" stop-color="black"/></radialGradient>
|
|
46
|
+
<radialGradient id="copper-light"><stop stop-color="#fa7138" stop-opacity=".16"/><stop offset="1" stop-color="#fa7138" stop-opacity="0"/></radialGradient>
|
|
47
|
+
<mask id="floor-mask"><rect width="640" height="510" fill="url(#floor-fade)"/></mask>
|
|
48
|
+
<pattern id="deck-grid" width="56" height="32" patternUnits="userSpaceOnUse"><path d="M28 0 56 16 28 32 0 16Z" stroke="#39393b" stroke-width=".55" fill="none"/></pattern>
|
|
49
|
+
<filter id="unit-shadow" x="-60%" y="-100%" width="220%" height="300%"><feGaussianBlur stdDeviation="11"/></filter>
|
|
50
|
+
<filter id="wire-glow" x="-100%" y="-100%" width="300%" height="300%"><feGaussianBlur stdDeviation="3"/></filter>
|
|
51
|
+
</defs>
|
|
52
|
+
<ellipse cx="335" cy="320" rx="260" ry="180" fill="url(#copper-light)"/>
|
|
53
|
+
<g mask="url(#floor-mask)"><path d="M-10 280 330 82 680 284 330 510Z" fill="url(#deck-grid)"/><path d="M31 318 330 145 628 318 330 490Z" fill="none" stroke="#515154" stroke-opacity=".3" stroke-width=".7"/></g>
|
|
54
|
+
<g class="graph-wires" fill="none" stroke-linejoin="round" stroke-linecap="round">
|
|
55
|
+
<path d="M293 368 348 336 348 274 388 251" stroke="#ff763d" stroke-width="9" opacity=".12" filter="url(#wire-glow)"/>
|
|
56
|
+
<path d="M220 431 286 469 370 420 421 420" stroke="#ff763d" stroke-width="9" opacity=".1" filter="url(#wire-glow)"/>
|
|
57
|
+
<path d="M293 368 348 336 348 274 388 251" stroke="#78442d" stroke-width="3"/>
|
|
58
|
+
<path d="M220 431 286 469 370 420 421 420" stroke="#78442d" stroke-width="3"/>
|
|
59
|
+
<path class="signal signal-one" d="M293 368 348 336 348 274 388 251" stroke="#ff9a63" stroke-width="2"/>
|
|
60
|
+
<path class="signal signal-two" d="M220 431 286 469 370 420 421 420" stroke="#ff9a63" stroke-width="2"/>
|
|
61
|
+
<circle cx="348" cy="336" r="4" fill="#0b0b0c" stroke="#c56538" stroke-width="1.5"/>
|
|
62
|
+
<circle cx="286" cy="469" r="4" fill="#0b0b0c" stroke="#c56538" stroke-width="1.5"/>
|
|
63
|
+
</g>
|
|
64
|
+
<g class="hardware hardware-server"><polygon points="432.0,179.0 504.7,221.0 432.0,263.0 359.3,221.0" fill="#000" stroke="none" stroke-width=".7" filter="url(#unit-shadow)"/><polygon points="432.0,72.0 492.6,107.0 432.0,142.0 371.4,107.0" fill="url(#metal-top)" stroke="#58585b" stroke-width=".7" /><polygon points="371.4,107.0 432.0,142.0 432.0,250.0 371.4,215.0" fill="url(#metal-left)" stroke="#58585b" stroke-width=".7" /><polygon points="492.6,107.0 432.0,142.0 432.0,250.0 492.6,215.0" fill="url(#metal-right)" stroke="#58585b" stroke-width=".7" /><polygon points="432.0,77.7 482.2,106.7 432.0,135.7 381.8,106.7" fill="#262629" stroke="#737378" stroke-width=".7" /><ellipse cx="432.0" cy="81.0" rx="1.5" ry=".8" fill="#a0a0a2"/><ellipse cx="475.3" cy="106.0" rx="1.5" ry=".8" fill="#a0a0a2"/><ellipse cx="432.0" cy="131.0" rx="1.5" ry=".8" fill="#a0a0a2"/><ellipse cx="388.7" cy="106.0" rx="1.5" ry=".8" fill="#a0a0a2"/><path d="M371.4 211.0 L432.0 246.0 L492.6 211.0" stroke="#6d6d71" stroke-opacity=".5" stroke-width=".5" fill="none"/><path d="M371.4 111.0 L432.0 146.0 L492.6 111.0" stroke="#6d6d71" stroke-opacity=".5" stroke-width=".5" fill="none"/><polygon points="377.4,181.5 425.9,209.5 425.9,228.5 377.4,200.5" fill="#101012" stroke="#444447" stroke-width=".7" /><path d="M383.5 199.0 L383.5 191.0" stroke="#59595d" stroke-width=".65"/><path d="M387.0 201.0 L387.0 193.0" stroke="#59595d" stroke-width=".65"/><path d="M390.4 203.0 L390.4 195.0" stroke="#59595d" stroke-width=".65"/><path d="M393.9 205.0 L393.9 197.0" stroke="#59595d" stroke-width=".65"/><path d="M397.4 207.0 L397.4 199.0" stroke="#59595d" stroke-width=".65"/><path d="M400.8 209.0 L400.8 201.0" stroke="#59595d" stroke-width=".65"/><path d="M404.3 211.0 L404.3 203.0" stroke="#59595d" stroke-width=".65"/><path d="M407.8 213.0 L407.8 205.0" stroke="#59595d" stroke-width=".65"/><path d="M411.2 215.0 L411.2 207.0" stroke="#59595d" stroke-width=".65"/><path d="M414.7 217.0 L414.7 209.0" stroke="#59595d" stroke-width=".65"/><path d="M418.1 219.0 L418.1 211.0" stroke="#59595d" stroke-width=".65"/><ellipse cx="421.6" cy="216.0" rx="1.6" ry="1" fill="#db976c"/><polygon points="377.4,151.5 425.9,179.5 425.9,198.5 377.4,170.5" fill="#101012" stroke="#444447" stroke-width=".7" /><path d="M383.5 169.0 L383.5 161.0" stroke="#59595d" stroke-width=".65"/><path d="M387.0 171.0 L387.0 163.0" stroke="#59595d" stroke-width=".65"/><path d="M390.4 173.0 L390.4 165.0" stroke="#59595d" stroke-width=".65"/><path d="M393.9 175.0 L393.9 167.0" stroke="#59595d" stroke-width=".65"/><path d="M397.4 177.0 L397.4 169.0" stroke="#59595d" stroke-width=".65"/><path d="M400.8 179.0 L400.8 171.0" stroke="#59595d" stroke-width=".65"/><path d="M404.3 181.0 L404.3 173.0" stroke="#59595d" stroke-width=".65"/><path d="M407.8 183.0 L407.8 175.0" stroke="#59595d" stroke-width=".65"/><path d="M411.2 185.0 L411.2 177.0" stroke="#59595d" stroke-width=".65"/><path d="M414.7 187.0 L414.7 179.0" stroke="#59595d" stroke-width=".65"/><path d="M418.1 189.0 L418.1 181.0" stroke="#59595d" stroke-width=".65"/><ellipse cx="421.6" cy="186.0" rx="1.6" ry="1" fill="#db976c"/><polygon points="377.4,121.5 425.9,149.5 425.9,168.5 377.4,140.5" fill="#101012" stroke="#444447" stroke-width=".7" /><path d="M383.5 139.0 L383.5 131.0" stroke="#59595d" stroke-width=".65"/><path d="M387.0 141.0 L387.0 133.0" stroke="#59595d" stroke-width=".65"/><path d="M390.4 143.0 L390.4 135.0" stroke="#59595d" stroke-width=".65"/><path d="M393.9 145.0 L393.9 137.0" stroke="#59595d" stroke-width=".65"/><path d="M397.4 147.0 L397.4 139.0" stroke="#59595d" stroke-width=".65"/><path d="M400.8 149.0 L400.8 141.0" stroke="#59595d" stroke-width=".65"/><path d="M404.3 151.0 L404.3 143.0" stroke="#59595d" stroke-width=".65"/><path d="M407.8 153.0 L407.8 145.0" stroke="#59595d" stroke-width=".65"/><path d="M411.2 155.0 L411.2 147.0" stroke="#59595d" stroke-width=".65"/><path d="M414.7 157.0 L414.7 149.0" stroke="#59595d" stroke-width=".65"/><path d="M418.1 159.0 L418.1 151.0" stroke="#59595d" stroke-width=".65"/><ellipse cx="421.6" cy="156.0" rx="1.6" ry="1" fill="#db976c"/><path d="M481.4 204.5 L481.4 130.5" stroke="#070708" stroke-width="1.5"/><path d="M477.9 206.5 L477.9 132.5" stroke="#070708" stroke-width="1.5"/><path d="M474.4 208.5 L474.4 134.5" stroke="#070708" stroke-width="1.5"/><path d="M471.0 210.5 L471.0 136.5" stroke="#070708" stroke-width="1.5"/><path d="M467.5 212.5 L467.5 138.5" stroke="#070708" stroke-width="1.5"/><path d="M464.0 214.5 L464.0 140.5" stroke="#070708" stroke-width="1.5"/><path d="M460.6 216.5 L460.6 142.5" stroke="#070708" stroke-width="1.5"/><path d="M457.1 218.5 L457.1 144.5" stroke="#070708" stroke-width="1.5"/><path d="M453.6 220.5 L453.6 146.5" stroke="#070708" stroke-width="1.5"/><path d="M450.2 222.5 L450.2 148.5" stroke="#070708" stroke-width="1.5"/><path d="M446.7 224.5 L446.7 150.5" stroke="#070708" stroke-width="1.5"/><path d="M443.3 226.5 L443.3 152.5" stroke="#070708" stroke-width="1.5"/><path d="M439.8 228.5 L439.8 154.5" stroke="#070708" stroke-width="1.5"/></g><g class="hardware hardware-agent"><polygon points="218.0,335.0 323.7,396.0 218.0,457.0 112.3,396.0" fill="#000" stroke="none" stroke-width=".7" filter="url(#unit-shadow)"/><polygon points="218.0,281.0 311.5,335.0 218.0,389.0 124.5,335.0" fill="url(#metal-top)" stroke="#58585b" stroke-width=".7" /><polygon points="124.5,335.0 218.0,389.0 218.0,444.0 124.5,390.0" fill="url(#metal-left)" stroke="#58585b" stroke-width=".7" /><polygon points="311.5,335.0 218.0,389.0 218.0,444.0 311.5,390.0" fill="url(#metal-right)" stroke="#58585b" stroke-width=".7" /><polygon points="218.0,286.7 301.1,334.7 218.0,382.7 134.9,334.7" fill="#262629" stroke="#737378" stroke-width=".7" /><ellipse cx="218.0" cy="290.0" rx="1.5" ry=".8" fill="#a0a0a2"/><ellipse cx="294.2" cy="334.0" rx="1.5" ry=".8" fill="#a0a0a2"/><ellipse cx="218.0" cy="378.0" rx="1.5" ry=".8" fill="#a0a0a2"/><ellipse cx="141.8" cy="334.0" rx="1.5" ry=".8" fill="#a0a0a2"/><path d="M124.5 386.0 L218.0 440.0 L311.5 386.0" stroke="#6d6d71" stroke-opacity=".5" stroke-width=".5" fill="none"/><path d="M124.5 339.0 L218.0 393.0 L311.5 339.0" stroke="#6d6d71" stroke-opacity=".5" stroke-width=".5" fill="none"/><polygon points="218.0,304.0 270.0,334.0 218.0,364.0 166.0,334.0" fill="url(#copper-top)" stroke="#fc9f6c" stroke-width=".7" /><polyline points="201.5,324.5 217.1,315.5 232.7,324.5 217.1,333.5" fill="none" stroke="#321b13" stroke-width="3.5" stroke-linejoin="round"/><polyline points="202.4,341.0 218.0,332.0 233.6,341.0 218.0,350.0" fill="none" stroke="#321b13" stroke-width="3.5" stroke-linejoin="round"/><path d="M139.2 384.5 L139.2 369.5" stroke="#0a0a0b" stroke-width="2"/><path d="M144.4 387.5 L144.4 372.5" stroke="#0a0a0b" stroke-width="2"/><path d="M149.6 390.5 L149.6 375.5" stroke="#0a0a0b" stroke-width="2"/><path d="M154.8 393.5 L154.8 378.5" stroke="#0a0a0b" stroke-width="2"/><path d="M160.0 396.5 L160.0 381.5" stroke="#0a0a0b" stroke-width="2"/><path d="M165.2 399.5 L165.2 384.5" stroke="#0a0a0b" stroke-width="2"/><path d="M170.4 402.5 L170.4 387.5" stroke="#0a0a0b" stroke-width="2"/><path d="M175.6 405.5 L175.6 390.5" stroke="#0a0a0b" stroke-width="2"/><path d="M180.8 408.5 L180.8 393.5" stroke="#0a0a0b" stroke-width="2"/><path d="M186.0 411.5 L186.0 396.5" stroke="#0a0a0b" stroke-width="2"/><path d="M191.2 414.5 L191.2 399.5" stroke="#0a0a0b" stroke-width="2"/><path d="M196.3 417.5 L196.3 402.5" stroke="#0a0a0b" stroke-width="2"/><path d="M201.5 420.5 L201.5 405.5" stroke="#0a0a0b" stroke-width="2"/><path d="M206.7 423.5 L206.7 408.5" stroke="#0a0a0b" stroke-width="2"/><polygon points="298.5,374.5 276.9,387.0 276.9,398.0 298.5,385.5" fill="#070708" stroke="#343437" stroke-width=".7" /><ellipse cx="269.1" cy="396.5" rx="2.5" ry="1.5" fill="#ff8a4c"/></g><g class="hardware hardware-mini"><polygon points="470.0,389.0 557.5,439.5 493.4,476.5 405.9,426.0" fill="#000" stroke="none" stroke-width=".7" filter="url(#unit-shadow)"/><polygon points="470.0,358.0 545.3,401.5 493.4,431.5 418.0,388.0" fill="url(#metal-top)" stroke="#58585b" stroke-width=".7" /><polygon points="418.0,388.0 493.4,431.5 493.4,463.5 418.0,420.0" fill="url(#metal-left)" stroke="#58585b" stroke-width=".7" /><polygon points="545.3,401.5 493.4,431.5 493.4,463.5 545.3,433.5" fill="url(#metal-right)" stroke="#58585b" stroke-width=".7" /><polygon points="470.0,363.7 535.0,401.2 493.4,425.2 428.4,387.7" fill="#262629" stroke="#737378" stroke-width=".7" /><ellipse cx="470.0" cy="367.0" rx="1.5" ry=".8" fill="#a0a0a2"/><ellipse cx="528.0" cy="400.5" rx="1.5" ry=".8" fill="#a0a0a2"/><ellipse cx="493.4" cy="420.5" rx="1.5" ry=".8" fill="#a0a0a2"/><ellipse cx="435.4" cy="387.0" rx="1.5" ry=".8" fill="#a0a0a2"/><path d="M418.0 416.0 L493.4 459.5 L545.3 429.5" stroke="#6d6d71" stroke-opacity=".5" stroke-width=".5" fill="none"/><path d="M418.0 392.0 L493.4 435.5 L545.3 405.5" stroke="#6d6d71" stroke-opacity=".5" stroke-width=".5" fill="none"/><path d="M432.8 419.5 L432.8 408.5" stroke="#0b0b0d" stroke-width="1.8"/><path d="M437.1 422.0 L437.1 411.0" stroke="#0b0b0d" stroke-width="1.8"/><path d="M441.4 424.5 L441.4 413.5" stroke="#0b0b0d" stroke-width="1.8"/><path d="M445.8 427.0 L445.8 416.0" stroke="#0b0b0d" stroke-width="1.8"/><path d="M450.1 429.5 L450.1 418.5" stroke="#0b0b0d" stroke-width="1.8"/><path d="M454.4 432.0 L454.4 421.0" stroke="#0b0b0d" stroke-width="1.8"/><path d="M458.7 434.5 L458.7 423.5" stroke="#0b0b0d" stroke-width="1.8"/><path d="M463.1 437.0 L463.1 426.0" stroke="#0b0b0d" stroke-width="1.8"/><path d="M467.4 439.5 L467.4 428.5" stroke="#0b0b0d" stroke-width="1.8"/><path d="M471.7 442.0 L471.7 431.0" stroke="#0b0b0d" stroke-width="1.8"/><path d="M476.1 444.5 L476.1 433.5" stroke="#0b0b0d" stroke-width="1.8"/><path d="M480.4 447.0 L480.4 436.0" stroke="#0b0b0d" stroke-width="1.8"/><polygon points="473.5,372.0 519.4,398.5 489.9,415.5 444.0,389.0" fill="#333337" stroke="#5e5e62" stroke-width=".7" /><ellipse cx="532.4" cy="428.0" rx="2" ry="1.2" fill="#bcbcc0"/></g><g fill="none" stroke="#77777b" stroke-width=".65" opacity=".65"><path d="M145 322 109 301H30"/><circle cx="145" cy="322" r="2"/><path d="M492 157 549 124h54"/><circle cx="492" cy="157" r="2"/><path d="m515 458 22 13h49"/></g>
|
|
65
|
+
<g fill="#747477" font-family="monospace" font-size="8" letter-spacing="1"><text x="50" y="415">DC / 01</text><text x="540" y="195">02</text><text x="540" y="490">03</text></g>
|
|
66
|
+
<g stroke="#57575b" stroke-width=".65"><path d="M27 120h8m-4-4v8M598 370h8m-4-4v8M353 64h8m-4-4v8"/></g>
|
|
67
|
+
</svg>
|
|
68
|
+
<div class="graph-label graph-label-agent"><strong data-i18n="guide.visual.myAgent">本机 Agent</strong><span data-i18n="guide.visual.myComputer">你正在用的电脑</span></div>
|
|
69
|
+
<div class="graph-label graph-label-target"><strong data-i18n="guide.visual.otherDevice">自己的设备</strong><span data-i18n="guide.visual.homeServer">例如:家里的服务器</span></div>
|
|
70
|
+
</div>
|
|
71
|
+
<div class="scene-query"><span class="query-symbol" aria-hidden="true">>_</span><blockquote data-i18n="guide.visual.request">“帮我看看家里服务器的日志。”</blockquote><span class="query-arrow" aria-hidden="true">↵</span></div>
|
|
72
|
+
<div class="scene-resources"><span><svg class="icon" aria-hidden="true"><use href="#icon-memory"/></svg><span data-i18n="panel.8">内存</span></span><span><svg class="icon" aria-hidden="true"><use href="#icon-disk"/></svg><span data-i18n="panel.9">磁盘</span></span><span><svg class="icon" aria-hidden="true"><use href="#icon-log"/></svg><span data-i18n="guide.visual.log">授权日志</span></span></div>
|
|
73
|
+
</figure>
|
|
29
74
|
</section>
|
|
30
|
-
<
|
|
31
|
-
<
|
|
32
|
-
<
|
|
33
|
-
<
|
|
75
|
+
<div class="scenarios" aria-label="使用场景" data-i18n-aria-label="guide.visual.scenarios">
|
|
76
|
+
<div><svg class="icon" aria-hidden="true"><use href="#icon-log"/></svg><p><strong data-i18n="guide.visual.debug">服务报错时</strong><span data-i18n="guide.visual.debugBody">让 Agent 读取已授权日志</span></p></div>
|
|
77
|
+
<div><svg class="icon" aria-hidden="true"><use href="#icon-memory"/></svg><p><strong data-i18n="guide.visual.save">买云资源前</strong><span data-i18n="guide.visual.saveBody">先看看已有电脑的资源</span></p></div>
|
|
78
|
+
<div><svg class="icon" aria-hidden="true"><use href="#icon-cloud"/></svg><p><strong data-i18n="guide.visual.away">出门在外时</strong><span data-i18n="guide.visual.awayBody">设备在线,就能查看回报状态</span></p></div>
|
|
79
|
+
</div>
|
|
80
|
+
<section class="install-section" aria-labelledby="install-title">
|
|
81
|
+
<div class="section-heading">
|
|
82
|
+
<p class="eyebrow"><span class="action-marker" aria-hidden="true">↘</span><span data-i18n="guide.focus.start">开始操作</span></p>
|
|
83
|
+
<h2 id="install-title" tabindex="-1" data-i18n="guide.focus.startTitle">接入,从这里开始</h2>
|
|
84
|
+
<p class="section-intro" data-i18n="guide.focus.startBody">选好使用方式,再选交给 Agent 或手动安装。目标设备没有 Agent 也能接入。</p>
|
|
85
|
+
<p class="section-note" data-i18n="guide.visual.noInstall">复制不会执行安装</p>
|
|
86
|
+
</div>
|
|
87
|
+
<div class="action-workbench">
|
|
88
|
+
<fieldset class="mode-options">
|
|
89
|
+
<legend><span class="action-number" aria-hidden="true">01</span><span data-i18n="guide.focus.select">选择使用方式</span></legend>
|
|
90
|
+
<div class="choices">
|
|
91
|
+
<label class="mode-choice">
|
|
92
|
+
<input type="radio" name="install-mode" value="local" checked>
|
|
93
|
+
<span class="choice-icon"><svg class="icon" aria-hidden="true"><use href="#icon-computer"/></svg></span>
|
|
94
|
+
<span class="choice-copy"><strong data-i18n="guide.local">本机使用</strong><span data-i18n="guide.visual.localBody">本机面板 + MCP,无需账号。</span></span>
|
|
95
|
+
</label>
|
|
96
|
+
<label class="mode-choice">
|
|
97
|
+
<input type="radio" name="install-mode" value="official">
|
|
98
|
+
<span class="choice-icon"><svg class="icon" aria-hidden="true"><use href="#icon-cloud"/></svg></span>
|
|
99
|
+
<span class="choice-copy"><strong data-i18n="guide.hosted">官方托管</strong><span data-i18n="guide.visual.hostedBody">用自己的账号绑定设备,使用加密中转。</span></span>
|
|
100
|
+
</label>
|
|
101
|
+
</div>
|
|
102
|
+
<details class="custom">
|
|
103
|
+
<summary data-i18n="guide.custom">已有自己的控制面?</summary>
|
|
104
|
+
<label class="self-hosted-choice"><input type="radio" name="install-mode" value="self-hosted"><span data-i18n="guide.focus.useSelfHosted">使用我的自建服务</span></label>
|
|
105
|
+
<div id="custom-fields" hidden>
|
|
106
|
+
<label for="custom-origin" data-i18n="guide.address">自建控制面的 HTTPS 地址</label>
|
|
107
|
+
<input id="custom-origin" type="url" placeholder="https://devices.example.com" aria-describedby="copy-result" autocomplete="off" spellcheck="false">
|
|
108
|
+
<p class="hint" data-i18n="guide.customDesc">连接已经部署的服务;不会替你部署服务器或迁移原有绑定。</p>
|
|
109
|
+
</div>
|
|
110
|
+
</details>
|
|
111
|
+
</fieldset>
|
|
112
|
+
<div class="copy-step">
|
|
113
|
+
<fieldset class="method-options">
|
|
114
|
+
<legend class="action-heading"><span class="action-number" aria-hidden="true">02</span><span data-i18n="guide.method.title">选择安装方式</span></legend>
|
|
115
|
+
<div class="method-switch">
|
|
116
|
+
<label><input type="radio" name="install-method" value="agent" checked><span data-i18n="guide.method.agent">交给 Agent</span></label>
|
|
117
|
+
<label><input type="radio" name="install-method" value="manual"><span data-i18n="guide.method.manual">手动安装</span></label>
|
|
118
|
+
</div>
|
|
119
|
+
</fieldset>
|
|
120
|
+
<div id="manual-options" hidden>
|
|
121
|
+
<p class="hint manual-prerequisites" data-i18n="guide.manual.prerequisites">macOS / Linux · Node.js 24+ · 全新安装。Windows 原生版暂未支持;已有安装会停止并保留配置。</p>
|
|
122
|
+
<fieldset class="pairing-options" id="pairing-options" hidden>
|
|
123
|
+
<legend data-i18n="guide.manual.browserQuestion">目标设备能打开浏览器吗?</legend>
|
|
124
|
+
<div class="pairing-choices">
|
|
125
|
+
<label><input type="radio" name="pairing-method" value="browser" checked><span data-i18n="guide.manual.hasBrowser">有浏览器</span></label>
|
|
126
|
+
<label><input type="radio" name="pairing-method" value="headless"><span data-i18n="guide.manual.noBrowser">无浏览器 / 服务器</span></label>
|
|
127
|
+
</div>
|
|
128
|
+
</fieldset>
|
|
129
|
+
</div>
|
|
130
|
+
<button class="primary" id="copy-instructions" type="button"><svg class="icon" aria-hidden="true"><use href="#icon-copy"/></svg><span id="copy-label" data-i18n="guide.localCopy">复制本机安装说明</span><svg class="icon copy-arrow" aria-hidden="true"><use href="#icon-arrow"/></svg></button>
|
|
131
|
+
<p class="copy-hint" id="copy-hint" data-i18n="guide.focus.copyHint">这是给 Agent 的说明,请粘贴到 Agent 对话中,而不是终端。</p>
|
|
132
|
+
<p id="copy-result" role="status" aria-live="polite" aria-atomic="true"></p>
|
|
133
|
+
<details id="instruction-details"><summary id="instruction-preview" data-i18n="guide.preview">查看或手动复制完整说明</summary><textarea id="install-instructions" aria-label="Agent 安装说明" data-i18n-aria-label="guide.instructions" rows="9" readonly spellcheck="false"></textarea></details>
|
|
134
|
+
</div>
|
|
135
|
+
<div class="next-action" id="next-action" data-copied="false">
|
|
136
|
+
<h3 class="action-heading" id="walkthrough-title" tabindex="-1"><span class="action-number" aria-hidden="true">03</span><span data-i18n="walk.title">复制后,照图操作</span></h3>
|
|
137
|
+
<p class="walkthrough-disclaimer" data-i18n="walk.disclaimer">以下是操作示意;请在对应电脑的真实窗口操作。</p>
|
|
138
|
+
<div id="install-walkthrough"></div>
|
|
139
|
+
<a class="binding-link" href="https://devices.owenshen.top/login" data-hosted-dashboard data-i18n="guide.focus.openHosted" hidden>安装后,打开面板完成本人绑定 ↗</a>
|
|
140
|
+
</div>
|
|
141
|
+
</div>
|
|
34
142
|
</section>
|
|
35
|
-
<
|
|
36
|
-
|
|
37
|
-
<div class="
|
|
38
|
-
<details><summary
|
|
143
|
+
<p class="trust-line"><svg class="icon" aria-hidden="true"><use href="#icon-shield"/></svg><span data-i18n="guide.visual.trust">私钥留在设备上 · 读取日志需要另外授权</span></p>
|
|
144
|
+
<section class="more-section" aria-label="详细说明" data-i18n-aria-label="guide.visual.details">
|
|
145
|
+
<details><summary data-i18n="guide.visual.pairDetails">安装和绑定的详细步骤</summary><div class="detail-content"><p data-i18n="guide.paste"></p><ol><li data-i18n="guide.pair1"></li><li data-i18n="guide.pair2"></li><li data-i18n="guide.pair3"></li></ol><p class="hint" data-i18n="guide.localHint"></p></div></details>
|
|
146
|
+
<details><summary data-i18n="guide.try">试用时看这四件事</summary><div class="detail-content checks"><div><h3 data-i18n="guide.resources"></h3><p data-i18n="guide.resourcesBody"></p></div><div><h3 data-i18n="guide.names"></h3><p data-i18n="guide.namesBody"></p></div><div><h3 data-i18n="guide.refresh"></h3><p data-i18n="guide.refreshBody"></p></div><div><h3 data-i18n="guide.agent"></h3><p data-i18n="guide.agentBody"></p></div></div></details>
|
|
147
|
+
<details><summary data-i18n="guide.scope">这版的范围</summary><div class="detail-content"><p data-i18n="guide.scopeBody"></p><p data-i18n="guide.quota"></p></div></details>
|
|
148
|
+
<details><summary data-i18n="guide.faq">遇到问题先查什么?</summary><div class="detail-content"><p data-i18n="guide.faqBody"></p><p data-i18n="guide.feedback"></p></div></details>
|
|
39
149
|
</section>
|
|
40
|
-
<aside><strong>这版的范围</strong><p>支持真实资源、设备说明、手动采集和经单独授权的日志尾读。暂不提供任意远程命令、通用文件传输、Windows 原生 Driver、自动网络扫描、离线局域网授权或本机/云端说明同步。</p><p>官方中转为试用额度:每账号每日 100 MiB(UTC),每方向 16 KiB/s;不是无限带宽服务。服务与应用为手动登记,未经自动检测。</p></aside>
|
|
41
150
|
</main>
|
|
42
|
-
<footer><a href="/install/agent.md">Agent
|
|
151
|
+
<footer><a href="/install/agent.md" data-i18n="guide.full">Agent 完整安装指南(中文)</a><a href="/install/trial.md" data-i18n="guide.markdown">文字版试用指南(中文)</a><a href="https://www.npmjs.com/package/device-center/v/0.2.0-beta.3" target="_blank" rel="noopener noreferrer" data-i18n="guide.source">MIT npm 源码包 ↗</a><span data-i18n="guide.footer">本机安装 · 私钥留在设备 · 操作单独授权</span></footer>
|
|
43
152
|
<script type="module" src="/src/start.js"></script>
|
|
44
153
|
</body>
|
|
45
154
|
</html>
|