protocol-proxy 2.5.0 → 2.5.1

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "protocol-proxy",
3
- "version": "2.5.0",
3
+ "version": "2.5.1",
4
4
  "description": "OpenAI / Anthropic 协议转换透明代理",
5
5
  "main": "server.js",
6
6
  "bin": {
package/public/app.js CHANGED
@@ -380,6 +380,42 @@ function renderProviderOptions() {
380
380
  });
381
381
  }
382
382
 
383
+ function attachMaskedKeyClick(span) {
384
+ span.style.cursor = 'pointer';
385
+ span.title = '点击修改 API Key';
386
+ span.addEventListener('click', () => {
387
+ const row = span.closest('.api-key-entry');
388
+ const group = span.parentElement;
389
+ const input = document.createElement('input');
390
+ input.type = 'password';
391
+ input.className = 'api-key-input';
392
+ input.placeholder = '输入新的 API Key...';
393
+ group.replaceChild(input, span);
394
+ input.focus();
395
+ input.addEventListener('blur', async () => {
396
+ const val = input.value.trim();
397
+ if (!val) {
398
+ restoreMaskedSpan(group, input, row);
399
+ return;
400
+ }
401
+ if (await showConfirm('确认修改此 API Key?<br>取消将恢复为 ****', '确认修改')) {
402
+ row.dataset.masked = 'false';
403
+ } else {
404
+ row.dataset.masked = 'true';
405
+ restoreMaskedSpan(group, input, row);
406
+ }
407
+ });
408
+ });
409
+ }
410
+
411
+ function restoreMaskedSpan(group, input, row) {
412
+ const restored = document.createElement('span');
413
+ restored.className = 'api-key-display';
414
+ restored.textContent = '****';
415
+ group.replaceChild(restored, input);
416
+ attachMaskedKeyClick(restored);
417
+ }
418
+
383
419
  function renderApiKeys(provider) {
384
420
  const container = document.getElementById('api-keys-list');
385
421
  if (!container) return;
@@ -407,6 +443,10 @@ function renderApiKeys(provider) {
407
443
  </div>
408
444
  `).join('');
409
445
 
446
+ container.querySelectorAll('.api-key-display').forEach(span => {
447
+ attachMaskedKeyClick(span);
448
+ });
449
+
410
450
  container.querySelectorAll('.api-key-remove').forEach(btn => {
411
451
  btn.addEventListener('click', () => {
412
452
  btn.closest('.api-key-entry').remove();
@@ -453,7 +493,12 @@ function initApiKeyAddBtn() {
453
493
  });
454
494
  }
455
495
 
456
- function selectProvider(id) {
496
+ function hasUnsavedMaskedKeyEdits() {
497
+ return !!document.querySelector('#api-keys-list .api-key-entry[data-index][data-masked="false"]');
498
+ }
499
+
500
+ async function selectProvider(id) {
501
+ if (hasUnsavedMaskedKeyEdits() && !await showConfirm('当前有未保存的 API Key 修改,切换供应商将丢失,确认切换?', '确认切换')) return;
457
502
  const provider = providers.find(p => p.id === id);
458
503
  document.getElementById('provider-id').value = id || '';
459
504
  const protocol = provider ? provider.protocol : '';
@@ -958,14 +1003,14 @@ function copyProxyUrl(port, btn) {
958
1003
  });
959
1004
  }
960
1005
 
961
- function showConfirm(text) {
1006
+ function showConfirm(text, okText = '删除') {
962
1007
  return new Promise(resolve => {
963
1008
  const modal = document.getElementById('confirm-modal');
964
1009
  document.getElementById('confirm-text').innerHTML = text;
965
- modal.classList.add('active');
966
-
967
1010
  const okBtn = document.getElementById('confirm-ok');
968
1011
  const cancelBtn = document.getElementById('confirm-cancel');
1012
+ okBtn.textContent = okText;
1013
+ modal.classList.add('active');
969
1014
 
970
1015
  function cleanup(result) {
971
1016
  modal.classList.remove('active');
package/public/style.css CHANGED
@@ -793,6 +793,10 @@ form {
793
793
  }
794
794
 
795
795
  /* Confirm modal */
796
+ .confirm-modal {
797
+ align-items: center;
798
+ }
799
+
796
800
  .confirm-modal .confirm-box {
797
801
  background: rgba(15, 23, 42, 0.8);
798
802
  backdrop-filter: blur(24px);
@@ -1277,6 +1281,13 @@ form {
1277
1281
  color: #64748b;
1278
1282
  font-size: 0.9rem;
1279
1283
  letter-spacing: 2px;
1284
+ cursor: pointer;
1285
+ transition: border-color 0.2s, color 0.2s;
1286
+ }
1287
+
1288
+ .api-key-display:hover {
1289
+ border-color: rgba(99, 102, 241, 0.5);
1290
+ color: #94a3b8;
1280
1291
  }
1281
1292
 
1282
1293
  .api-key-remove {