codex-endpoint-switcher 1.1.0 → 1.3.0
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/package.json +3 -3
- package/src/main/cloud-sync-client.js +12 -7
- package/src/renderer/index.html +182 -158
- package/src/renderer/renderer.js +223 -85
- package/src/renderer/styles.css +526 -130
- package/src/web/server.js +26 -1
package/src/renderer/renderer.js
CHANGED
|
@@ -16,7 +16,10 @@ function createWebBridge() {
|
|
|
16
16
|
|
|
17
17
|
const payload = await response.json();
|
|
18
18
|
if (!response.ok || !payload.ok) {
|
|
19
|
-
|
|
19
|
+
const error = new Error(payload.error || `请求失败:${response.status}`);
|
|
20
|
+
error.statusCode = response.status;
|
|
21
|
+
error.payload = payload;
|
|
22
|
+
throw error;
|
|
20
23
|
}
|
|
21
24
|
|
|
22
25
|
return payload.data;
|
|
@@ -106,6 +109,15 @@ function $(selector) {
|
|
|
106
109
|
return document.querySelector(selector);
|
|
107
110
|
}
|
|
108
111
|
|
|
112
|
+
function setText(selector, value) {
|
|
113
|
+
const element = $(selector);
|
|
114
|
+
if (!element) {
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
element.textContent = value;
|
|
119
|
+
}
|
|
120
|
+
|
|
109
121
|
function formatDateTime(value) {
|
|
110
122
|
if (!value) {
|
|
111
123
|
return "-";
|
|
@@ -123,9 +135,18 @@ function formatDateTime(value) {
|
|
|
123
135
|
}
|
|
124
136
|
|
|
125
137
|
function setStatus(message, type = "info") {
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
138
|
+
void message;
|
|
139
|
+
void type;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function setAuthStatus(message, type = "info") {
|
|
143
|
+
const authStatusElement = $("#authStatusBox");
|
|
144
|
+
if (!authStatusElement) {
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
authStatusElement.textContent = message;
|
|
149
|
+
authStatusElement.className = `status-box ${type} auth-status`;
|
|
129
150
|
}
|
|
130
151
|
|
|
131
152
|
function syncFieldValue(selector, value) {
|
|
@@ -141,12 +162,59 @@ function syncFieldValue(selector, value) {
|
|
|
141
162
|
input.value = value || "";
|
|
142
163
|
}
|
|
143
164
|
|
|
165
|
+
function applyAccessState(loggedIn) {
|
|
166
|
+
const authGate = $("#authGate");
|
|
167
|
+
const appShell = $("#appShell");
|
|
168
|
+
|
|
169
|
+
if (authGate) {
|
|
170
|
+
authGate.hidden = loggedIn;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (appShell) {
|
|
174
|
+
appShell.hidden = !loggedIn;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (!loggedIn && $("#endpointModal") && !$("#endpointModal").hidden) {
|
|
178
|
+
closeEndpointModal();
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function isUnauthorizedError(error) {
|
|
183
|
+
return Number(error?.statusCode || 0) === 401;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
function setEndpointModalContent(mode, note = "") {
|
|
187
|
+
const isEdit = mode === "edit";
|
|
188
|
+
$("#endpointModalTitle").textContent = isEdit ? "编辑连接" : "新增连接";
|
|
189
|
+
$("#endpointModalText").textContent = isEdit
|
|
190
|
+
? `正在编辑“${note}”,保存后会直接更新这条连接。`
|
|
191
|
+
: "填写备注、URL、Key,保存后就能直接加入切换列表。";
|
|
192
|
+
$("#saveEndpointButton").textContent = isEdit ? "保存修改" : "新增连接";
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
function openEndpointModal() {
|
|
196
|
+
const modal = $("#endpointModal");
|
|
197
|
+
modal.hidden = false;
|
|
198
|
+
document.body.classList.add("modal-open");
|
|
199
|
+
|
|
200
|
+
window.requestAnimationFrame(() => {
|
|
201
|
+
const input = $("#endpointNote");
|
|
202
|
+
input?.focus();
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
function closeEndpointModal() {
|
|
207
|
+
const modal = $("#endpointModal");
|
|
208
|
+
modal.hidden = true;
|
|
209
|
+
document.body.classList.remove("modal-open");
|
|
210
|
+
}
|
|
211
|
+
|
|
144
212
|
function resetForm() {
|
|
145
213
|
$("#endpointId").value = "";
|
|
146
214
|
$("#endpointNote").value = "";
|
|
147
215
|
$("#endpointUrl").value = "";
|
|
148
216
|
$("#endpointKey").value = "";
|
|
149
|
-
|
|
217
|
+
setEndpointModalContent("create");
|
|
150
218
|
}
|
|
151
219
|
|
|
152
220
|
function fillForm(endpoint) {
|
|
@@ -154,7 +222,7 @@ function fillForm(endpoint) {
|
|
|
154
222
|
$("#endpointNote").value = endpoint.note;
|
|
155
223
|
$("#endpointUrl").value = endpoint.url;
|
|
156
224
|
$("#endpointKey").value = endpoint.key;
|
|
157
|
-
|
|
225
|
+
setEndpointModalContent("edit", endpoint.note);
|
|
158
226
|
setStatus(`正在编辑:${endpoint.note}`, "info");
|
|
159
227
|
}
|
|
160
228
|
|
|
@@ -164,25 +232,11 @@ function renderCurrent() {
|
|
|
164
232
|
return;
|
|
165
233
|
}
|
|
166
234
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
$("#currentModel").textContent = current.model || "-";
|
|
173
|
-
$("#proxyModeStatus").textContent = current.proxyModeEnabled
|
|
174
|
-
? `已开启,固定代理:${current.proxyBaseUrl}`
|
|
175
|
-
: "未开启";
|
|
176
|
-
$("#proxyModeHint").textContent = current.proxyModeEnabled
|
|
177
|
-
? "当前 Codex 只要已经接入本地代理,后续同一会话内切换连接会在下一次请求时热更新。"
|
|
178
|
-
: "当前还是直连模式。开启后需要把已打开的旧 Codex 会话重开一次;之后同一会话即可热更新。";
|
|
179
|
-
$("#enableProxyModeButton").disabled = current.proxyModeEnabled;
|
|
180
|
-
$("#enableProxyModeButton").textContent = current.proxyModeEnabled
|
|
181
|
-
? "热更新模式已开启"
|
|
182
|
-
: "开启热更新模式";
|
|
183
|
-
$("#heroBadge").textContent = current.currentNote
|
|
184
|
-
? `${current.proxyModeEnabled ? "热更新中" : "当前连接"}:${current.currentNote}`
|
|
185
|
-
: "当前未匹配到已保存连接";
|
|
235
|
+
setText("#activeEndpointTag", current.currentNote || "未识别");
|
|
236
|
+
setText("#currentNote", current.currentNote || "未识别");
|
|
237
|
+
setText("#currentProvider", current.provider || "-");
|
|
238
|
+
setText("#currentKeyMasked", current.currentKeyMasked || "-");
|
|
239
|
+
setText("#currentModel", current.model || "-");
|
|
186
240
|
}
|
|
187
241
|
|
|
188
242
|
function renderCloudStatus() {
|
|
@@ -191,22 +245,15 @@ function renderCloudStatus() {
|
|
|
191
245
|
return;
|
|
192
246
|
}
|
|
193
247
|
|
|
194
|
-
syncFieldValue("#
|
|
195
|
-
syncFieldValue("#cloudUsername", cloud.username);
|
|
196
|
-
|
|
197
|
-
const authText = !cloud.serverUrl
|
|
198
|
-
? "未配置同步服务器"
|
|
199
|
-
: cloud.loggedIn
|
|
200
|
-
? `已登录:${cloud.remoteUser || cloud.username}`
|
|
201
|
-
: cloud.hasToken
|
|
202
|
-
? "本地已保存登录态,但远端校验未通过"
|
|
203
|
-
: "未登录";
|
|
248
|
+
syncFieldValue("#authUsername", cloud.username);
|
|
204
249
|
|
|
205
|
-
const
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
:
|
|
250
|
+
const accountName = cloud.remoteUser || cloud.username || "-";
|
|
251
|
+
const serverText = cloud.loggedIn ? "已连接" : cloud.lastError ? "连接异常" : "等待登录";
|
|
252
|
+
const sessionText = cloud.loggedIn
|
|
253
|
+
? "已登录"
|
|
254
|
+
: cloud.hasToken
|
|
255
|
+
? "登录态失效,请重新登录"
|
|
256
|
+
: "未登录";
|
|
210
257
|
|
|
211
258
|
const syncStatusParts = [];
|
|
212
259
|
if (cloud.lastPushAt) {
|
|
@@ -219,9 +266,15 @@ function renderCloudStatus() {
|
|
|
219
266
|
syncStatusParts.push("还没有推送或拉取记录");
|
|
220
267
|
}
|
|
221
268
|
|
|
222
|
-
$("#
|
|
223
|
-
$("#
|
|
269
|
+
$("#authAccessTag").textContent = cloud.loggedIn ? "已登录" : "未登录";
|
|
270
|
+
$("#cloudAccessTag").textContent = cloud.loggedIn ? "控制台已解锁" : "未登录";
|
|
271
|
+
$("#cloudAccountName").textContent = accountName;
|
|
272
|
+
$("#cloudServerStatus").textContent = serverText;
|
|
273
|
+
$("#cloudSessionStatus").textContent = cloud.lastError
|
|
274
|
+
? `${sessionText} · ${cloud.lastError}`
|
|
275
|
+
: sessionText;
|
|
224
276
|
$("#cloudLastSyncStatus").textContent = syncStatusParts.join(" / ");
|
|
277
|
+
$("#openSwitchAccountButton").disabled = !cloud.loggedIn;
|
|
225
278
|
$("#cloudLogoutButton").disabled = !cloud.hasToken;
|
|
226
279
|
$("#cloudPushButton").disabled = !cloud.loggedIn;
|
|
227
280
|
$("#cloudPullMergeButton").disabled = !cloud.loggedIn;
|
|
@@ -274,6 +327,7 @@ function createEndpointCard(endpoint) {
|
|
|
274
327
|
editButton.textContent = "编辑";
|
|
275
328
|
editButton.addEventListener("click", () => {
|
|
276
329
|
fillForm(endpoint);
|
|
330
|
+
openEndpointModal();
|
|
277
331
|
});
|
|
278
332
|
|
|
279
333
|
const deleteButton = document.createElement("button");
|
|
@@ -305,7 +359,7 @@ function renderEndpoints() {
|
|
|
305
359
|
if (state.endpoints.length === 0) {
|
|
306
360
|
const empty = document.createElement("div");
|
|
307
361
|
empty.className = "empty-state";
|
|
308
|
-
empty.textContent = "
|
|
362
|
+
empty.textContent = "当前还没有连接,点击右上角“新增连接”先建一条。";
|
|
309
363
|
list.appendChild(empty);
|
|
310
364
|
} else {
|
|
311
365
|
state.endpoints.forEach((endpoint) => {
|
|
@@ -316,6 +370,43 @@ function renderEndpoints() {
|
|
|
316
370
|
$("#endpointCount").textContent = `${state.endpoints.length} 条`;
|
|
317
371
|
}
|
|
318
372
|
|
|
373
|
+
async function handleAccessRevoked(message) {
|
|
374
|
+
try {
|
|
375
|
+
state.cloud = await bridge.getCloudSyncStatus();
|
|
376
|
+
renderCloudStatus();
|
|
377
|
+
} catch {
|
|
378
|
+
// 登录态接口异常时,至少先把控制台切回登录页。
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
applyAccessState(false);
|
|
382
|
+
setAuthStatus(message || "请先登录同步账号后再进入连接控制台。", "error");
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
async function bootstrapConsoleAccess() {
|
|
386
|
+
try {
|
|
387
|
+
const cloud = await bridge.getCloudSyncStatus();
|
|
388
|
+
state.cloud = cloud;
|
|
389
|
+
renderCloudStatus();
|
|
390
|
+
|
|
391
|
+
if (!cloud.loggedIn) {
|
|
392
|
+
applyAccessState(false);
|
|
393
|
+
if (cloud.hasToken && cloud.lastError) {
|
|
394
|
+
setAuthStatus(`登录校验失败:${cloud.lastError}`, "error");
|
|
395
|
+
} else {
|
|
396
|
+
setAuthStatus("请先登录同步账号后再进入连接控制台。", "info");
|
|
397
|
+
}
|
|
398
|
+
return;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
applyAccessState(true);
|
|
402
|
+
await refreshDashboard(false);
|
|
403
|
+
setStatus("已通过账号校验,连接控制台已解锁。", "success");
|
|
404
|
+
} catch (error) {
|
|
405
|
+
applyAccessState(false);
|
|
406
|
+
setAuthStatus(`登录校验失败:${error.message}`, "error");
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
|
|
319
410
|
async function refreshDashboard(showMessage = true) {
|
|
320
411
|
try {
|
|
321
412
|
const [current, endpoints, paths, cloud] = await Promise.all([
|
|
@@ -338,6 +429,11 @@ async function refreshDashboard(showMessage = true) {
|
|
|
338
429
|
setStatus("已刷新当前连接状态。", "success");
|
|
339
430
|
}
|
|
340
431
|
} catch (error) {
|
|
432
|
+
if (isUnauthorizedError(error)) {
|
|
433
|
+
await handleAccessRevoked(error.message);
|
|
434
|
+
return;
|
|
435
|
+
}
|
|
436
|
+
|
|
341
437
|
setStatus(`刷新失败:${error.message}`, "error");
|
|
342
438
|
}
|
|
343
439
|
}
|
|
@@ -357,60 +453,52 @@ async function handleSwitchEndpoint(id, note) {
|
|
|
357
453
|
}
|
|
358
454
|
return result;
|
|
359
455
|
} catch (error) {
|
|
456
|
+
if (isUnauthorizedError(error)) {
|
|
457
|
+
await handleAccessRevoked(error.message);
|
|
458
|
+
return null;
|
|
459
|
+
}
|
|
460
|
+
|
|
360
461
|
setStatus(`切换失败:${error.message}`, "error");
|
|
361
462
|
return null;
|
|
362
463
|
}
|
|
363
464
|
}
|
|
364
465
|
|
|
365
|
-
|
|
366
|
-
try {
|
|
367
|
-
setStatus("正在切到热更新代理模式 ...", "info");
|
|
368
|
-
const result = await bridge.enableProxyMode();
|
|
369
|
-
await refreshDashboard(false);
|
|
370
|
-
if (result.oneTimeRestartRequired) {
|
|
371
|
-
setStatus(
|
|
372
|
-
"热更新模式已开启。请把当前已经打开着的旧 Codex 会话重开一次;之后同一会话内即可热更新。",
|
|
373
|
-
"success",
|
|
374
|
-
);
|
|
375
|
-
} else {
|
|
376
|
-
setStatus("热更新模式已开启。当前会话后续请求可直接热更新到新连接。", "success");
|
|
377
|
-
}
|
|
378
|
-
} catch (error) {
|
|
379
|
-
setStatus(`开启热更新模式失败:${error.message}`, "error");
|
|
380
|
-
}
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
function getCloudFormPayload() {
|
|
466
|
+
function getAuthFormPayload() {
|
|
384
467
|
return {
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
password: $("#cloudPassword").value,
|
|
468
|
+
username: $("#authUsername").value.trim(),
|
|
469
|
+
password: $("#authPassword").value,
|
|
388
470
|
};
|
|
389
471
|
}
|
|
390
472
|
|
|
391
473
|
async function handleCloudRegister() {
|
|
392
474
|
try {
|
|
393
|
-
|
|
394
|
-
const payload =
|
|
475
|
+
setAuthStatus("正在注册同步账号 ...", "info");
|
|
476
|
+
const payload = getAuthFormPayload();
|
|
395
477
|
const result = await bridge.registerCloudAccount(payload);
|
|
396
|
-
$("#
|
|
478
|
+
$("#authPassword").value = "";
|
|
479
|
+
state.cloud = result;
|
|
480
|
+
renderCloudStatus();
|
|
481
|
+
applyAccessState(true);
|
|
397
482
|
await refreshDashboard(false);
|
|
398
483
|
setStatus(result.message || "账号注册成功。", "success");
|
|
399
484
|
} catch (error) {
|
|
400
|
-
|
|
485
|
+
setAuthStatus(`注册失败:${error.message}`, "error");
|
|
401
486
|
}
|
|
402
487
|
}
|
|
403
488
|
|
|
404
489
|
async function handleCloudLogin() {
|
|
405
490
|
try {
|
|
406
|
-
|
|
407
|
-
const payload =
|
|
491
|
+
setAuthStatus("正在登录同步账号 ...", "info");
|
|
492
|
+
const payload = getAuthFormPayload();
|
|
408
493
|
const result = await bridge.loginCloudAccount(payload);
|
|
409
|
-
$("#
|
|
494
|
+
$("#authPassword").value = "";
|
|
495
|
+
state.cloud = result;
|
|
496
|
+
renderCloudStatus();
|
|
497
|
+
applyAccessState(true);
|
|
410
498
|
await refreshDashboard(false);
|
|
411
499
|
setStatus(result.message || "账号登录成功。", "success");
|
|
412
500
|
} catch (error) {
|
|
413
|
-
|
|
501
|
+
setAuthStatus(`登录失败:${error.message}`, "error");
|
|
414
502
|
}
|
|
415
503
|
}
|
|
416
504
|
|
|
@@ -418,10 +506,13 @@ async function handleCloudLogout() {
|
|
|
418
506
|
try {
|
|
419
507
|
setStatus("正在退出同步账号 ...", "info");
|
|
420
508
|
const result = await bridge.logoutCloudAccount();
|
|
421
|
-
|
|
422
|
-
|
|
509
|
+
$("#authPassword").value = "";
|
|
510
|
+
state.cloud = result;
|
|
511
|
+
renderCloudStatus();
|
|
512
|
+
applyAccessState(false);
|
|
513
|
+
setAuthStatus(result.message || "已退出同步账号。", "success");
|
|
423
514
|
} catch (error) {
|
|
424
|
-
|
|
515
|
+
setAuthStatus(`退出失败:${error.message}`, "error");
|
|
425
516
|
}
|
|
426
517
|
}
|
|
427
518
|
|
|
@@ -435,6 +526,11 @@ async function handleCloudPush() {
|
|
|
435
526
|
"success",
|
|
436
527
|
);
|
|
437
528
|
} catch (error) {
|
|
529
|
+
if (isUnauthorizedError(error)) {
|
|
530
|
+
await handleAccessRevoked(error.message);
|
|
531
|
+
return;
|
|
532
|
+
}
|
|
533
|
+
|
|
438
534
|
setStatus(`推送失败:${error.message}`, "error");
|
|
439
535
|
}
|
|
440
536
|
}
|
|
@@ -461,6 +557,11 @@ async function handleCloudPull(mode) {
|
|
|
461
557
|
"success",
|
|
462
558
|
);
|
|
463
559
|
} catch (error) {
|
|
560
|
+
if (isUnauthorizedError(error)) {
|
|
561
|
+
await handleAccessRevoked(error.message);
|
|
562
|
+
return;
|
|
563
|
+
}
|
|
564
|
+
|
|
464
565
|
setStatus(`拉取失败:${error.message}`, "error");
|
|
465
566
|
}
|
|
466
567
|
}
|
|
@@ -480,15 +581,20 @@ async function handleSubmitEndpoint(event) {
|
|
|
480
581
|
try {
|
|
481
582
|
if (id) {
|
|
482
583
|
await bridge.updateEndpoint({ id, note, url, key });
|
|
483
|
-
setStatus(`已更新连接:${note}`, "success");
|
|
484
584
|
} else {
|
|
485
585
|
await bridge.createEndpoint({ note, url, key });
|
|
486
|
-
setStatus(`已新增连接:${note}`, "success");
|
|
487
586
|
}
|
|
488
587
|
|
|
489
|
-
resetForm();
|
|
490
588
|
await refreshDashboard(false);
|
|
589
|
+
closeEndpointModal();
|
|
590
|
+
resetForm();
|
|
591
|
+
setStatus(id ? `已更新连接:${note}` : `已新增连接:${note}`, "success");
|
|
491
592
|
} catch (error) {
|
|
593
|
+
if (isUnauthorizedError(error)) {
|
|
594
|
+
await handleAccessRevoked(error.message);
|
|
595
|
+
return;
|
|
596
|
+
}
|
|
597
|
+
|
|
492
598
|
setStatus(`保存失败:${error.message}`, "error");
|
|
493
599
|
}
|
|
494
600
|
}
|
|
@@ -502,11 +608,17 @@ async function handleDeleteEndpoint(id, note) {
|
|
|
502
608
|
try {
|
|
503
609
|
await bridge.deleteEndpoint({ id });
|
|
504
610
|
if ($("#endpointId").value.trim() === id) {
|
|
611
|
+
closeEndpointModal();
|
|
505
612
|
resetForm();
|
|
506
613
|
}
|
|
507
614
|
await refreshDashboard(false);
|
|
508
615
|
setStatus(`已删除连接:${note}`, "success");
|
|
509
616
|
} catch (error) {
|
|
617
|
+
if (isUnauthorizedError(error)) {
|
|
618
|
+
await handleAccessRevoked(error.message);
|
|
619
|
+
return;
|
|
620
|
+
}
|
|
621
|
+
|
|
510
622
|
setStatus(`删除失败:${error.message}`, "error");
|
|
511
623
|
}
|
|
512
624
|
}
|
|
@@ -520,23 +632,45 @@ async function handleOpenPath(targetPath, label) {
|
|
|
520
632
|
|
|
521
633
|
setStatus(`已打开${label}。`, "success");
|
|
522
634
|
} catch (error) {
|
|
635
|
+
if (isUnauthorizedError(error)) {
|
|
636
|
+
await handleAccessRevoked(error.message);
|
|
637
|
+
return;
|
|
638
|
+
}
|
|
639
|
+
|
|
523
640
|
setStatus(`打开${label}失败:${error.message}`, "error");
|
|
524
641
|
}
|
|
525
642
|
}
|
|
526
643
|
|
|
527
644
|
function bindEvents() {
|
|
645
|
+
$("#authForm").addEventListener("submit", (event) => {
|
|
646
|
+
event.preventDefault();
|
|
647
|
+
handleCloudLogin();
|
|
648
|
+
});
|
|
649
|
+
$("#authRegisterButton").addEventListener("click", () => {
|
|
650
|
+
handleCloudRegister();
|
|
651
|
+
});
|
|
528
652
|
$("#refreshButton").addEventListener("click", () => {
|
|
529
653
|
refreshDashboard();
|
|
530
654
|
});
|
|
655
|
+
$("#openCreateEndpointButton").addEventListener("click", () => {
|
|
656
|
+
resetForm();
|
|
657
|
+
openEndpointModal();
|
|
658
|
+
});
|
|
659
|
+
$("#closeEndpointModalButton").addEventListener("click", () => {
|
|
660
|
+
closeEndpointModal();
|
|
661
|
+
});
|
|
662
|
+
$("#endpointModal").addEventListener("click", (event) => {
|
|
663
|
+
if (event.target.dataset.modalClose === "true") {
|
|
664
|
+
closeEndpointModal();
|
|
665
|
+
}
|
|
666
|
+
});
|
|
531
667
|
$("#endpointForm").addEventListener("submit", handleSubmitEndpoint);
|
|
532
668
|
$("#clearFormButton").addEventListener("click", () => {
|
|
533
669
|
resetForm();
|
|
534
|
-
setStatus("
|
|
670
|
+
setStatus("已重置表单,可作为新连接保存。", "info");
|
|
535
671
|
});
|
|
536
|
-
$("#enableProxyModeButton").addEventListener("click", handleEnableProxyMode);
|
|
537
|
-
$("#cloudRegisterButton").addEventListener("click", handleCloudRegister);
|
|
538
|
-
$("#cloudLoginButton").addEventListener("click", handleCloudLogin);
|
|
539
672
|
$("#cloudLogoutButton").addEventListener("click", handleCloudLogout);
|
|
673
|
+
$("#openSwitchAccountButton").addEventListener("click", handleCloudLogout);
|
|
540
674
|
$("#cloudPushButton").addEventListener("click", handleCloudPush);
|
|
541
675
|
$("#cloudPullMergeButton").addEventListener("click", () => {
|
|
542
676
|
handleCloudPull("merge");
|
|
@@ -554,11 +688,15 @@ function bindEvents() {
|
|
|
554
688
|
handleOpenPath(state.paths.endpointStorePath, " 连接数据文件");
|
|
555
689
|
}
|
|
556
690
|
});
|
|
691
|
+
window.addEventListener("keydown", (event) => {
|
|
692
|
+
if (event.key === "Escape" && !$("#endpointModal").hidden) {
|
|
693
|
+
closeEndpointModal();
|
|
694
|
+
}
|
|
695
|
+
});
|
|
557
696
|
}
|
|
558
697
|
|
|
559
698
|
window.addEventListener("DOMContentLoaded", async () => {
|
|
560
699
|
bindEvents();
|
|
561
700
|
resetForm();
|
|
562
|
-
await
|
|
563
|
-
setStatus("应用已就绪,你可以直接新增 URL / Key / 备注 并切换。", "success");
|
|
701
|
+
await bootstrapConsoleAccess();
|
|
564
702
|
});
|