PageSourceSearch

https://lynn2728-gcli2api.hf.space/

html lynn2728-gcli2api.hf.space collected 2026-10-03 17:04:47 UTC 101,596 bytes, 2,413 lines download raw bytes

1<!DOCTYPE html>
2<html lang="zh-CN">
3
4<head>
5    <meta charset="UTF-8">
6    <meta name="viewport" content="width=device-width, initial-scale=1.0">
7    <title>GCLI2API 控制面板</title>
8    <style>
9        body {
10            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif;
11            max-width: 1000px;
12            margin: 0 auto;
13            padding: 20px;
14            background-color: #f8f9fa;
15        }
16
17        .container {
18            background-color: white;
19            padding: 30px;
20            border-radius: 10px;
21            box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
22            box-sizing: border-box;
23            overflow-x: auto;
24        }
25
26        h1 {
27            color: #333;
28            text-align: center;
29        }
30
31        .form-group {
32            margin-bottom: 20px;
33        }
34
35        label {
36            display: block;
37            margin-bottom: 5px;
38            font-weight: bold;
39            color: #555;
40        }
41
42        input[type="text"] {
43            width: 100%;
44            padding: 10px;
45            border: 2px solid #ddd;
46            border-radius: 5px;
47            font-size: 16px;
48            box-sizing: border-box;
49        }
50
51        input[type="text"]:focus {
52            border-color: #4285f4;
53            outline: none;
54        }
55
56        .btn {
57            background-color: #28a745;
58            color: white;
59            padding: 12px 30px;
60            border: none;
61            border-radius: 5px;
62            font-size: 16px;
63            cursor: pointer;
64            width: 100%;
65            margin-bottom: 10px;
66        }
67
68        .btn:hover {
69            background-color: #218838;
70        }
71
72        .btn:disabled {
73            background-color: #ccc;
74            cursor: not-allowed;
75        }
76
77        .auth-url {
78            background-color: #f8f9fa;
79            border: 1px solid #e1e4e8;
80            border-radius: 5px;
81            padding: 15px;
82            margin: 20px 0;
83            word-break: break-all;
84        }
85
86        .auth-url a {
87            color: #4285f4;
88            text-decoration: none;
89        }
90
91        .auth-url a:hover {
92            text-decoration: underline;
93        }
94
95        .credentials {
96            background-color: #f0f8ff;
97            border: 1px solid #b0d4ff;
98            border-radius: 5px;
99            padding: 15px;
100            margin: 20px 0;
101            font-family: monospace;
102            font-size: 12px;
103            white-space: pre-wrap;
104            word-break: break-all;
105            max-height: 400px;
106            overflow-y: auto;
107        }
108
109        /* Toast 固定定位在右上角 */
110        #statusSection {
111            position: fixed;
112            top: 20px;
113            right: 20px;
114            left: auto;
115            transform: none;
116            z-index: 9999;
117            width: auto;
118            max-width: 400px;
119            min-width: 250px;
120        }
121
122        /* Toast 专用样式 - 只在 #statusSection 内生效 */
123        #statusSection .status {
124            padding: 12px 20px;
125            border-radius: 8px;
126            margin: 0;
127            box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
128            opacity: 0;
129            transform: translateX(100%);
130            transition: opacity 0.3s ease, transform 0.3s ease;
131        }
132
133        #statusSection .status.show {
134            opacity: 1;
135            transform: translateX(0);
136        }
137
138        #statusSection .status.fade-out {
139            opacity: 0;
140            transform: translateX(100%);
141        }
142
143        #statusSection .status.success {
144            background-color: #28a745;
145            border: none;
146            color: white;
147        }
148
149        #statusSection .status.error {
150            background-color: #dc3545;
151            border: none;
152            color: white;
153        }
154
155        #statusSection .status.warning {
156            background-color: #ffc107;
157            border: none;
158            color: #212529;
159        }
160
161        #statusSection .status.info {
162            background-color: #17a2b8;
163            border: none;
164            color: white;
165        }
166
167        /* 页面内嵌的 status 样式 - 保持原有风格 */
168        .status {
169            padding: 10px;
170            border-radius: 5px;
171            margin: 10px 0;
172        }
173
174        .status.success {
175            background-color: #d4edda;
176            border: 1px solid #c3e6cb;
177            color: #155724;
178        }
179
180        .status.error {
181            background-color: #f8d7da;
182            border: 1px solid #f5c6cb;
183            color: #721c24;
184        }
185
186        .status.info {
187            background-color: #d1ecf1;
188            border: 1px solid #bee5eb;
189            color: #0c5460;
190        }
191
192        .hidden {
193            display: none;
194        }
195
196        .loading {
197            text-align: center;
198            color: #666;
199        }
200
201        .login-form {
202            text-align: center;
203            padding: 50px 0;
204        }
205
206        .login-form input[type="password"] {
207            width: 300px;
208            padding: 12px;
209            border: 2px solid #ddd;
210            border-radius: 5px;
211            font-size: 16px;
212            margin-bottom: 20px;
213            box-sizing: border-box;
214        }
215
216        .tabs {
217            display: inline-flex;
218            background: linear-gradient(145deg, #f5f5f7, #e8e8ed);
219            padding: 6px;
220            border-radius: 14px;
221            margin-bottom: 25px;
222            border-bottom: none;
223            gap: 3px;
224            overflow-x: auto;
225            max-width: 100%;
226            user-select: none;
227            box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.06),
228                0 1px 2px rgba(255, 255, 255, 0.9);
229            position: relative;
230        }
231
232        /* 滑块指示器 */
233        .tab-slider {
234            position: absolute;
235            top: 6px;
236            left: 0;
237            right: 0;
238            height: calc(100% - 12px);
239            background: white;
240            border-radius: 10px;
241            box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1),
242                0 1px 3px rgba(0, 0, 0, 0.06),
243                inset 0 -1px 0 rgba(0, 0, 0, 0.02);
244            transition: left 0.3s cubic-bezier(0.4, 0, 0.2, 1),
245                right 0.3s cubic-bezier(0.4, 0, 0.2, 1);
246            z-index: 0;
247            pointer-events: none;
248        }
249
250        /* 滑块微光效果 */
251        .tab-slider::after {
252            content: '';
253            position: absolute;
254            top: 0;
255            left: 0;
256            right: 0;
257            height: 50%;
258            background: linear-gradient(180deg,
259                    rgba(255, 255, 255, 0.8) 0%,
260                    rgba(255, 255, 255, 0) 100%);
261            border-radius: 10px 10px 0 0;
262            pointer-events: none;
263            opacity: 0.5;
264        }
265
266        .tabs::-webkit-scrollbar {
267            height: 4px;
268        }
269
270        .tabs::-webkit-scrollbar-track {
271            background: transparent;
272        }
273
274        .tabs::-webkit-scrollbar-thumb {
275            background: rgba(0, 0, 0, 0.15);
276            border-radius: 2px;
277        }
278
279        .tabs::-webkit-scrollbar-thumb:hover {
280            background: rgba(0, 0, 0, 0.25);
281        }
282
283        .tab {
284            padding: 10px 18px;
285            cursor: pointer;
286            border: none;
287            background: transparent;
288            border-radius: 10px;
289            color: #666;
290            font-size: 14px;
291            font-weight: 450;
292            transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
293            white-space: nowrap;
294            position: relative;
295            overflow: hidden;
296            z-index: 1;
297        }
298
299        /* 点击波纹效果 */
300        .tab::before {
301            content: '';
302            position: absolute;
303            top: 50%;
304            left: 50%;
305            width: 0;
306            height: 0;
307            border-radius: 50%;
308            background: rgba(66, 133, 244, 0.15);
309            transform: translate(-50%, -50%);
310            transition: width 0.4s ease, height 0.4s ease;
311            z-index: -1;
312        }
313
314        .tab:active::before {
315            width: 200%;
316            height: 200%;
317        }
318
319        .tab.active {
320            color: #1a1a1a;
321            font-weight: 550;
322            transform: translateY(0);
323            /* 背景和阴影由滑块提供 */
324        }
325
326        .tab:hover:not(.active) {
327            background: rgba(255, 255, 255, 0.6);
328            color: #333;
329            transform: translateY(-1px);
330            box-shadow: 0 2px 4px rgba(0, 0, 0, 0.04);
331        }
332
333        /* 按压效果 */
334        .tab:active {
335            transform: scale(0.97) translateY(0);
336            transition: transform 0.1s ease;
337        }
338
339        .tab.active:active {
340            transform: scale(0.98);
341            box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08),
342                inset 0 1px 2px rgba(0, 0, 0, 0.02);
343        }
344
345        /* 焦点状态(键盘导航) */
346        .tab:focus {
347            outline: none;
348        }
349
350        .tab:focus-visible {
351            outline: 2px solid rgba(66, 133, 244, 0.5);
352            outline-offset: 2px;
353        }
354
355        .tab-content {
356            display: none;
357            width: 100%;
358            box-sizing: border-box;
359            /* 动画由 JavaScript 控制,避免冲突 */
360        }
361
362        .tab-content.active {
363            display: block;
364        }
365
366        .upload-area {
367            border: 2px dashed #ddd;
368            border-radius: 5px;
369            padding: 40px;
370            text-align: center;
371            background-color: #fafafa;
372            margin: 20px 0;
373            cursor: pointer;
374            transition: border-color 0.3s;
375        }
376
377        .upload-area:hover {
378            border-color: #4285f4;
379        }
380
381        .upload-area.dragover {
382            border-color: #4285f4;
383            background-color: #f0f8ff;
384        }
385
386        .file-list {
387            margin: 20px 0;
388        }
389
390        .file-item {
391            background-color: #f8f9fa;
392            border: 1px solid #e1e4e8;
393            border-radius: 3px;
394            padding: 10px;
395            margin: 5px 0;
396            display: flex;
397            justify-content: space-between;
398            align-items: center;
399        }
400
401        .file-item .file-name {
402            font-family: monospace;
403            color: #333;
404        }
405
406        .file-item .file-size {
407            color: #666;
408            font-size: 12px;
409        }
410
411        .file-item .remove-btn {
412            background: #dc3545;
413            color: white;
414            border: none;
415            border-radius: 3px;
416            padding: 2px 8px;
417            cursor: pointer;
418            font-size: 12px;
419        }
420
421        .upload-progress {
422            background-color: #f8f9fa;
423            border: 1px solid #e1e4e8;
424            border-radius: 5px;
425            padding: 15px;
426            margin: 20px 0;
427        }
428
429        .progress-bar {
430            width: 100%;
431            height: 20px;
432            background-color: #e9ecef;
433            border-radius: 10px;
434            overflow: hidden;
435            margin: 10px 0;
436        }
437
438        .progress-fill {
439            height: 100%;
440            background-color: #28a745;
441            transition: width 0.3s ease;
442        }
443
444        /* 文件管理样式 */
445        .cred-card {
446            background-color: #f8f9fa;
447            border: 1px solid #e1e4e8;
448            border-radius: 8px;
449            padding: 15px;
450            margin: 10px 0;
451            position: relative;
452            width: 100%;
453            box-sizing: border-box;
454        }
455
456        .cred-card.disabled {
457            background-color: #f5f5f5;
458            border-color: #ccc;
459            opacity: 0.7;
460        }
461
462        .cred-header {
463            display: flex;
464            justify-content: space-between;
465            align-items: flex-start;
466            margin-bottom: 10px;
467            gap: 20px;
468        }
469
470        .cred-filename {
471            font-family: monospace;
472            font-weight: bold;
473            color: #333;
474            font-size: 14px;
475            white-space: nowrap;
476            overflow: hidden;
477            text-overflow: ellipsis;
478            min-width: 300px;
479        }
480
481        .cred-status {
482            display: flex;
483            gap: 5px;
484        }
485
486        .status-badge {
487            padding: 2px 8px;
488            border-radius: 12px;
489            font-size: 12px;
490            color: white;
491        }
492
493        .status-badge.enabled {
494            background-color: #28a745;
495        }
496
497        .status-badge.disabled {
498            background-color: #6c757d;
499        }
500
501        .error-codes {
502            background-color: #f8d7da;
503            color: #721c24;
504            padding: 2px 8px;
505            border-radius: 12px;
506            font-size: 12px;
507        }
508
509        .cooldown-badge {
510            background-color: #ffc107;
511            color: #856404;
512            padding: 2px 8px;
513            border-radius: 12px;
514            font-size: 12px;
515            font-weight: bold;
516        }
517
518        .cooldown-badge.ready {
519            background-color: #28a745;
520            color: white;
521        }
522
523        .model-cooldown-details {
524            background-color: #e3f2fd;
525            border: 1px solid #90caf9;
526            border-radius: 4px;
527            padding: 8px;
528            margin-top: 8px;
529            font-size: 11px;
530            color: #1976d2;
531        }
532
533        .model-cooldown-item {
534            display: inline-block;
535            background-color: #64b5f6;
536            color: white;
537            padding: 2px 6px;
538            border-radius: 10px;
539            margin: 2px;
540            font-size: 10px;
541        }
542
543        .cred-actions {
544            display: flex;
545            gap: 5px;
546            flex-wrap: wrap;
547        }
548
549        .cred-btn {
550            padding: 4px 12px;
551            border: none;
552            border-radius: 4px;
553            font-size: 12px;
554            cursor: pointer;
555            transition: background-color 0.2s;
556            background-color: #28a745;
557            color: white;
558        }
559
560        .cred-btn:hover {
561            background-color: #218838;
562        }
563
564        .cred-btn.enable {
565            background-color: #28a745;
566            color: white;
567        }
568
569        .cred-btn.disable {
570            background-color: #28a745;
571            color: white;
572        }
573
574        .cred-btn.delete {
575            background-color: #dc3545;
576            color: white;
577        }
578
579        .cred-btn.delete:hover {
580            background-color: #c82333;
581        }
582
583        .cred-btn.download {
584            background-color: #28a745;
585            color: white;
586        }
587
588        .cred-btn.view {
589            background-color: #28a745;
590            color: white;
591        }
592
593        .cred-details {
594            margin-top: 10px;
595            display: none;
596        }
597
598        .cred-details.show {
599            display: block;
600        }
601
602        .cred-content {
603            background-color: #f0f8ff;
604            border: 1px solid #b0d4ff;
605            border-radius: 4px;
606            padding: 10px;
607            font-family: monospace;
608            font-size: 11px;
609            white-space: pre-wrap;
610            word-break: break-all;
611            max-height: 200px;
612            overflow-y: auto;
613        }
614
615        /* 额度信息显示样式 */
616        .cred-quota-details {
617            margin-top: 10px;
618            animation: slideDown 0.3s ease-out;
619        }
620
621        @keyframes slideDown {
622            from {
623                opacity: 0;
624                transform: translateY(-10px);
625            }
626
627            to {
628                opacity: 1;
629                transform: translateY(0);
630            }
631        }
632
633        .cred-quota-content {
634            background: linear-gradient(to bottom, #ffffff, #f8f9fa);
635            border: 2px solid #17a2b8;
636            border-radius: 8px;
637            padding: 10px;
638            box-shadow: 0 2px 8px rgba(23, 162, 184, 0.15);
639        }
640
641        .manage-actions {
642            margin-bottom: 20px;
643            display: flex;
644            gap: 10px;
645            flex-wrap: wrap;
646        }
647
648        /* 文件管理新增样式 */
649        .stats-container {
650            display: flex;
651            gap: 15px;
652            margin-bottom: 20px;
653            flex-wrap: wrap;
654        }
655
656        .stat-item {
657            background: linear-gradient(45deg, #f8f9fa, #e9ecef);
658            border: 1px solid #dee2e6;
659            border-radius: 8px;
660            padding: 12px 20px;
661            text-align: center;
662            min-width: 120px;
663            box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
664        }
665
666        .stat-number {
667            font-size: 24px;
668            font-weight: bold;
669            color: #333;
670            display: block;
671        }
672
673        .stat-label {
674            font-size: 12px;
675            color: #666;
676            text-transform: uppercase;
677            margin-top: 4px;
678        }
679
680        .stat-item.total {
681            border-left: 4px solid #007bff;
682        }
683
684        .stat-item.normal {
685            border-left: 4px solid #28a745;
686        }
687
688        .stat-item.disabled {
689            border-left: 4px solid #6c757d;
690        }
691
692        .filter-container {
693            display: flex;
694            gap: 10px;
695            margin-bottom: 20px;
696            align-items: center;
697            flex-wrap: wrap;
698        }
699
700        .filter-select {
701            padding: 8px 12px;
702            border: 2px solid #ddd;
703            border-radius: 4px;
704            font-size: 14px;
705            background-color: white;
706        }
707
708        .filter-select:focus {
709            border-color: #4285f4;
710            outline: none;
711        }
712
713        .pagination-container {
714            display: flex;
715            justify-content: center;
716            align-items: center;
717            gap: 10px;
718            margin: 20px 0;
719            flex-wrap: wrap;
720        }
721
722        .pagination-info {
723            color: #666;
724            font-size: 14px;
725        }
726
727        .pagination-btn {
728            padding: 8px 12px;
729            border: 1px solid #ddd;
730            background: white;
731            cursor: pointer;
732            border-radius: 4px;
733            font-size: 14px;
734        }
735
736        .pagination-btn:hover:not(:disabled) {
737            background: #f8f9fa;
738            border-color: #4285f4;
739        }
740
741        .pagination-btn:disabled {
742            background: #f5f5f5;
743            color: #ccc;
744            cursor: not-allowed;
745        }
746
747        .pagination-btn.active {
748            background: #4285f4;
749            color: white;
750            border-color: #4285f4;
751        }
752
753        .page-size-select {
754            padding: 6px 10px;
755            border: 1px solid #ddd;
756            border-radius: 4px;
757            font-size: 14px;
758        }
759
760        .refresh-btn {
761            background-color: #28a745;
762            color: white;
763            padding: 8px 16px;
764            border: none;
765            border-radius: 4px;
766            cursor: pointer;
767        }
768
769        .download-all-btn {
770            background-color: #28a745;
771            color: white;
772            padding: 8px 16px;
773            border: none;
774            border-radius: 4px;
775            cursor: pointer;
776        }
777
778        .refresh-btn:hover,
779        .download-all-btn:hover {
780            background-color: #218838;
781        }
782
783        /* 批量操作样式 */
784        .batch-controls {
785            background-color: #f8f9fa;
786            border: 1px solid #e1e4e8;
787            border-radius: 8px;
788            padding: 15px;
789            margin-bottom: 20px;
790        }
791
792        .checkbox-container {
793            display: flex;
794            align-items: center;
795            margin-right: 15px;
796        }
797
798        .batch-actions {
799            display: flex;
800            gap: 10px;
801            flex-wrap: wrap;
802            align-items: center;
803            margin-top: 10px;
804        }
805
806        .batch-btn {
807            padding: 6px 12px;
808            border: none;
809            border-radius: 4px;
810            font-size: 12px;
811            cursor: pointer;
812            transition: background-color 0.2s;
813            background-color: #28a745;
814            color: white;
815        }
816
817        .batch-btn:hover:not(:disabled) {
818            background-color: #218838;
819        }
820
821        .batch-btn.batch-enable {
822            background-color: #28a745;
823            color: white;
824        }
825
826        .batch-btn.batch-disable {
827            background-color: #28a745;
828            color: white;
829        }
830
831        .batch-btn.batch-delete {
832            background-color: #dc3545;
833            color: white;
834        }
835
836        .batch-btn.batch-email {
837            background-color: #28a745;
838            color: white;
839        }
840
841        .batch-btn:disabled {
842            background-color: #e9ecef;
843            color: #6c757d;
844            cursor: not-allowed;
845        }
846
847
848        .cred-btn.email {
849            background-color: #28a745;
850            color: white;
851        }
852
853        .selected-count {
854            font-weight: bold;
855            color: #007bff;
856            margin-right: 10px;
857        }
858
859        .select-all-checkbox {
860            margin-right: 8px;
861            transform: scale(1.2);
862        }
863
864        /* 错误码筛选增强 */
865        .error-filter-container {
866            display: flex;
867            gap: 10px;
868            align-items: center;
869            flex-wrap: wrap;
870        }
871
872        .error-code-badge {
873            display: inline-block;
874            background-color: #dc3545;
875            color: white;
876            padding: 2px 6px;
877            border-radius: 10px;
878            font-size: 11px;
879            margin: 1px;
880            cursor: pointer;
881            transition: background-color 0.2s;
882        }
883
884        .error-code-badge:hover {
885            background-color: #c82333;
886        }
887
888        .error-code-badge.selected {
889            background-color: #007bff;
890        }
891
892        /* 配置管理样式 */
893        .config-group {
894            background-color: #f8f9fa;
895            border: 1px solid #e1e4e8;
896            border-radius: 8px;
897            padding: 20px;
898            margin: 15px 0;
899        }
900
901        .config-group h4 {
902            margin-top: 0;
903            margin-bottom: 15px;
904            color: #333;
905            border-bottom: 1px solid #e1e4e8;
906            padding-bottom: 8px;
907        }
908
909        .config-input {
910            width: 100%;
911            padding: 8px 12px;
912            border: 2px solid #ddd;
913            border-radius: 4px;
914            font-size: 14px;
915            box-sizing: border-box;
916            margin-bottom: 5px;
917        }
918
919        .config-input:focus {
920            border-color: #4285f4;
921            outline: none;
922        }
923
924        .config-input:disabled {
925            background-color: #f5f5f5;
926            color: #666;
927            cursor: not-allowed;
928        }
929
930        .config-checkbox {
931            margin-right: 8px;
932            transform: scale(1.2);
933        }
934
935        .config-note {
936            display: block;
937            color: #666;
938            font-size: 12px;
939            margin-bottom: 10px;
940            font-style: italic;
941        }
942
943        .config-info {
944            background-color: #e3f2fd;
945            border: 1px solid #1976d2;
946            border-radius: 4px;
947            padding: 12px;
948            margin-top: 8px;
949            font-size: 13px;
950            color: #1565c0;
951        }
952
953        .config-info ul {
954            margin: 8px 0 4px 0;
955            color: #424242;
956        }
957
958        .config-info li {
959            margin: 3px 0;
960        }
961
962        .env-locked {
963            position: relative;
964        }
965
966        .env-locked::after {
967            content: "🔒 环境变量锚定";
968            position: absolute;
969            right: 10px;
970            top: 50%;
971            transform: translateY(-50%);
972            background-color: #ffc107;
973            color: #212529;
974            padding: 2px 6px;
975            border-radius: 3px;
976            font-size: 11px;
977            pointer-events: none;
978        }
979
980        /* 使用统计样式 */
981        .usage-card {
982            background-color: #f8f9fa;
983            border: 1px solid #e1e4e8;
984            border-radius: 8px;
985            padding: 15px;
986            margin: 10px 0;
987            position: relative;
988        }
989
990        .usage-header {
991            display: flex;
992            justify-content: space-between;
993            align-items: center;
994            margin-bottom: 15px;
995        }
996
997        .usage-filename {
998            font-family: monospace;
999            font-weight: bold;
1000            color: #333;
1001            font-size: 14px;
1002        }
1003
1004        .usage-progress {
1005            margin: 10px 0;
1006        }
1007
1008        .usage-progress-label {
1009            display: flex;
1010            justify-content: space-between;
1011            align-items: center;
1012            margin-bottom: 5px;
1013            font-size: 12px;
1014        }
1015
1016        .usage-progress-bar {
1017            width: 100%;
1018            height: 20px;
1019            background-color: #e9ecef;
1020            border-radius: 10px;
1021            overflow: hidden;
1022            position: relative;
1023        }
1024
1025        .usage-progress-fill {
1026            height: 100%;
1027            transition: width 0.3s ease;
1028        }
1029
1030        .usage-progress-fill.gemini {
1031            background-color: #ff6b35;
1032        }
1033
1034        .usage-progress-fill.total {
1035            background-color: #007bff;
1036        }
1037
1038        .usage-progress-fill.warning {
1039            background-color: #ffc107;
1040        }
1041
1042        .usage-progress-fill.danger {
1043            background-color: #dc3545;
1044        }
1045
1046        .usage-actions {
1047            display: flex;
1048            gap: 5px;
1049            margin-top: 10px;
1050        }
1051
1052        .usage-btn {
1053            padding: 4px 8px;
1054            border: none;
1055            border-radius: 4px;
1056            font-size: 11px;
1057            cursor: pointer;
1058            transition: background-color 0.2s;
1059        }
1060
1061        .usage-btn.reset {
1062            background-color: #6c757d;
1063            color: white;
1064        }
1065
1066        .usage-btn.limits {
1067            background-color: #17a2b8;
1068            color: white;
1069        }
1070
1071        .usage-info {
1072            display: grid;
1073            grid-template-columns: 1fr 1fr;
1074            gap: 10px;
1075            margin-top: 10px;
1076            font-size: 12px;
1077        }
1078
1079        .usage-info-item {
1080            background-color: #ffffff;
1081            padding: 8px;
1082            border-radius: 4px;
1083            border: 1px solid #dee2e6;
1084        }
1085
1086        .usage-info-label {
1087            font-weight: bold;
1088            color: #666;
1089            display: block;
1090            margin-bottom: 2px;
1091        }
1092
1093        .usage-info-value {
1094            color: #333;
1095        }
1096
1097        .reset-time {
1098            font-size: 11px;
1099            color: #666;
1100            font-style: italic;
1101            margin-top: 5px;
1102        }
1103
1104        /* 限制设置弹窗样式 */
1105        .modal {
1106            display: none;
1107            position: fixed;
1108            z-index: 1000;
1109            left: 0;
1110            top: 0;
1111            width: 100%;
1112            height: 100%;
1113            background-color: rgba(0, 0, 0, 0.5);
1114        }
1115
1116        .modal-content {
1117            background-color: #fefefe;
1118            margin: 15% auto;
1119            padding: 20px;
1120            border-radius: 8px;
1121            width: 400px;
1122            max-width: 90%;
1123        }
1124
1125        .modal-header {
1126            display: flex;
1127            justify-content: space-between;
1128            align-items: center;
1129            margin-bottom: 15px;
1130            padding-bottom: 10px;
1131            border-bottom: 1px solid #dee2e6;
1132        }
1133
1134        .modal-title {
1135            margin: 0;
1136            font-size: 16px;
1137            color: #333;
1138        }
1139
1140        .modal-close {
1141            background: none;
1142            border: none;
1143            font-size: 20px;
1144            cursor: pointer;
1145            color: #999;
1146        }
1147
1148        .modal-close:hover {
1149            color: #333;
1150        }
1151
1152        .modal-body {
1153            margin-bottom: 15px;
1154        }
1155
1156        .modal-footer {
1157            display: flex;
1158            gap: 10px;
1159            justify-content: flex-end;
1160        }
1161
1162        /* 消息模态框样式 */
1163        .message-modal-overlay {
1164            position: fixed;
1165            top: 0;
1166            left: 0;
1167            width: 100%;
1168            height: 100%;
1169            background-color: rgba(0, 0, 0, 0.5);
1170            display: flex;
1171            justify-content: center;
1172            align-items: center;
1173            z-index: 10000;
1174            animation: fadeIn 0.2s ease-in;
1175        }
1176
1177        @keyframes fadeIn {
1178            from {
1179                opacity: 0;
1180            }
1181
1182            to {
1183                opacity: 1;
1184            }
1185        }
1186
1187        .message-modal {
1188            background: white;
1189            border-radius: 8px;
1190            box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
1191            max-width: 600px;
1192            width: 90%;
1193            max-height: 80vh;
1194            display: flex;
1195            flex-direction: column;
1196            animation: slideIn 0.3s ease-out;
1197        }
1198
1199        @keyframes slideIn {
1200            from {
1201                transform: translateY(-50px);
1202                opacity: 0;
1203            }
1204
1205            to {
1206                transform: translateY(0);
1207                opacity: 1;
1208            }
1209        }
1210
1211        .message-modal-header {
1212            display: flex;
1213            justify-content: space-between;
1214            align-items: center;
1215            padding: 20px 24px;
1216            border-bottom: 1px solid #e0e0e0;
1217        }
1218
1219        .message-modal.success .message-modal-header {
1220            background: linear-gradient(135deg, #4caf50 0%, #45a049 100%);
1221            color: white;
1222            border-radius: 8px 8px 0 0;
1223        }
1224
1225        .message-modal.error .message-modal-header {
1226            background: linear-gradient(135deg, #f44336 0%, #d32f2f 100%);
1227            color: white;
1228            border-radius: 8px 8px 0 0;
1229        }
1230
1231        .message-modal.info .message-modal-header {
1232            background: linear-gradient(135deg, #2196f3 0%, #1976d2 100%);
1233            color: white;
1234            border-radius: 8px 8px 0 0;
1235        }
1236
1237        .message-modal-header h3 {
1238            margin: 0;
1239            font-size: 20px;
1240            font-weight: 600;
1241        }
1242
1243        .message-modal-close {
1244            background: none;
1245            border: none;
1246            font-size: 28px;
1247            cursor: pointer;
1248            color: inherit;
1249            opacity: 0.8;
1250            transition: opacity 0.2s;
1251            padding: 0;
1252            width: 32px;
1253            height: 32px;
1254            display: flex;
1255            align-items: center;
1256            justify-content: center;
1257        }
1258
1259        .message-modal-close:hover {
1260            opacity: 1;
1261        }
1262
1263        .message-modal-body {
1264            padding: 24px;
1265            overflow-y: auto;
1266            line-height: 1.6;
1267            color: #333;
1268            font-size: 14px;
1269            white-space: pre-wrap;
1270            word-break: break-word;
1271        }
1272
1273        .message-modal-footer {
1274            padding: 16px 24px;
1275            border-top: 1px solid #e0e0e0;
1276            display: flex;
1277            justify-content: flex-end;
1278            gap: 10px;
1279        }
1280
1281        .message-modal-btn {
1282            padding: 10px 24px;
1283            border: none;
1284            border-radius: 4px;
1285            font-size: 14px;
1286            font-weight: 500;
1287            cursor: pointer;
1288            transition: all 0.2s;
1289            background-color: #4285f4;
1290            color: white;
1291        }
1292
1293        .message-modal-btn:hover {
1294            background-color: #3367d6;
1295            transform: translateY(-1px);
1296            box-shadow: 0 2px 8px rgba(66, 133, 244, 0.3);
1297        }
1298
1299        /* 消息中的链接样式 */
1300        .message-link {
1301            color: #1976d2;
1302            text-decoration: none;
1303            font-weight: 500;
1304            padding: 2px 4px;
1305            border-radius: 3px;
1306            background-color: rgba(25, 118, 210, 0.1);
1307            transition: all 0.2s;
1308            display: inline-block;
1309            word-break: break-all;
1310        }
1311
1312        .message-link:hover {
1313            background-color: rgba(25, 118, 210, 0.2);
1314            text-decoration: underline;
1315            transform: translateY(-1px);
1316        }
1317
1318        .message-link:active {
1319            transform: translateY(0);
1320        }
1321
1322        /* 移动端适配 */
1323        @media (max-width: 768px) {
1324            .message-modal {
1325                max-width: 95%;
1326                max-height: 90vh;
1327            }
1328
1329            .message-modal-header {
1330                padding: 16px 20px;
1331            }
1332
1333            .message-modal-body {
1334                padding: 20px;
1335                font-size: 13px;
1336            }
1337
1338            .message-modal-footer {
1339                padding: 12px 20px;
1340            }
1341        }
1342    </style>
1343</head>
1344
1345<body>
1346    <div class="container">
1347
1348        <!-- 登录界面 -->
1349        <div id="loginSection" class="login-form">
1350            <h1>GCLI2API 管理面板</h1>
1351            <p>请输入访问密码:</p>
1352            <input type="password" id="loginPassword" placeholder="输入密码" onkeypress="handlePasswordEnter(event)" />
1353            <br>
1354            <button class="btn" onclick="login()">登录</button>
1355        </div>
1356
1357        <!-- 主界面 -->
1358        <div id="mainSection" class="hidden">
1359            <div
1360                style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; flex-wrap: wrap; gap: 10px;">
1361                <div style="display: flex; align-items: center; gap: 15px; flex-wrap: wrap;">
1362                    <h1 style="margin: 0;">GCLI2API 管理面板</h1>
1363                    <span id="versionInfo" style="font-size: 12px; color: #666;">
1364                        <span id="versionText">加载中...</span>
1365                    </span>
1366                    <button onclick="checkForUpdates()" id="checkUpdateBtn"
1367                        style="padding: 4px 12px; background-color: #17a2b8; color: white; border: none; border-radius: 4px; font-size: 12px; cursor: pointer; white-space: nowrap;">
1368                        检查更新
1369                    </button>
1370                </div>
1371                <button onclick="logout()"
1372                    style="padding: 8px 20px; background-color: #dc3545; color: white; border: none; border-radius: 5px; font-size: 14px; cursor: pointer;">
1373                    退出登录
1374                </button>
1375            </div>
1376
1377            <!-- 标签页 -->
1378            <div class="tabs">
1379                <div class="tab-slider"></div>
1380                <button class="tab active" onclick="switchTab('oauth')">OAuth认证</button>
1381                <button class="tab" onclick="switchTab('antigravity')">Antigravity认证</button>
1382                <button class="tab" onclick="switchTab('upload')">批量上传</button>
1383                <button class="tab" onclick="switchTab('manage')">GCLI凭证管理</button>
1384                <button class="tab" onclick="switchTab('antigravity-manage')">Antigravity凭证管理</button>
1385                <button class="tab" onclick="switchTab('config')">配置管理</button>
1386                <button class="tab" onclick="switchTab('logs')">实时日志</button>
1387                <button class="tab" onclick="switchTab('about')">项目信息</button>
1388            </div>
1389
1390            <!-- OAuth认证标签页 -->
1391            <div id="oauthTab" class="tab-content active">
1392                <!-- API 自动启用说明 -->
1393                <div class="status success" style="margin-bottom: 20px;">
1394                    <strong>✨ 自动化优化:</strong> 系统现在会在认证成功后自动为您的项目启用必需的API服务
1395                    <ul style="margin: 10px 0; padding-left: 20px;">
1396                        <li><strong>Gemini Cloud Assist API</strong></li>
1397                        <li><strong>Gemini for Google Cloud API</strong></li>
1398                    </ul>
1399                    <p style="margin: 10px 0; color: #155724;"><strong>说明:</strong>无需手动启用API,系统会自动处理这些配置步骤,让认证流程更加顺畅。
1400                    </p>
1401                </div>
1402
1403                <!-- 折叠式 Project ID 输入框 -->
1404                <div class="form-group">
1405                    <div style="cursor: pointer; user-select: none; padding: 12px; border: 2px solid #ddd; border-radius: 5px; background: #f8f9fa; display: flex; justify-content: space-between; align-items: center;"
1406                        onclick="toggleProjectIdSection()">
1407                        <span style="font-weight: bold; color: #555;">📁 高级选项:Google Cloud Project ID
1408                            (不用管,直接点击获取链接即可)</span>
1409                        <span id="projectIdToggleIcon"
1410                            style="font-size: 14px; color: #666; transition: transform 0.3s ease;">▶</span>
1411                    </div>
1412                    <div id="projectIdSection"
1413                        style="display: none; margin-top: 15px; padding: 15px; border: 2px solid #ddd; border-top: none; border-radius: 0 0 5px 5px; background: #ffffff;">
1414                        <label for="projectId"
1415                            style="display: block; margin-bottom: 5px; font-weight: bold; color: #555;">Google Cloud
1416                            Project ID (可选):</label>
1417                        <input type="text" id="projectId"
1418                            style="width: 100%; padding: 10px; border: 2px solid #ddd; border-radius: 5px; font-size: 16px; box-sizing: border-box;"
1419                            placeholder="留空将尝试自动检测,或手动输入项目ID" />
1420                        <small style="color: #666; font-size: 12px; margin-top: 5px; display: block;">
1421                            💡 提示:如果你不懂这是什么,可以留空此字段让系统自动检测项目ID
1422                        </small>
1423                    </div>
1424                </div>
1425
1426                <button class="btn" id="getAuthBtn" onclick="startAuth()">获取认证链接</button>
1427
1428                <div id="authUrlSection" class="hidden">
1429                    <h3>认证链接:</h3>
1430                    <div class="auth-url">
1431                        <a id="authUrl" href="#" target="_blank">
1431点击此链接进行认证</a>
1432                    </div>
1433                    <div class="status info">
1434                        <strong>重要说明:</strong>
1435                        <ol style="margin: 10px 0; padding-left: 20px;">
1436                            <li>点击上方认证链接,会在新窗口中打开Google OAuth页面</li>
1437                            <li>完成Google账号登录和授权</li>
1438                            <li>授权成功后会跳转到localhost:11451显示成功页面</li>
1439                            <li>关闭OAuth窗口,返回本页面</li>
1440                            <li>点击下方"获取认证文件"按钮完成流程</li>
1441                        </ol>
1442                    </div>
1443
1444                    <!-- 快捷回调URL输入选项 -->
1445                    <div class="form-group"
1446                        style="margin: 20px 0; padding: 15px; border: 2px solid #e8f4fd; border-radius: 8px; background: #f8fcff;">
1447                        <div style="cursor: pointer; user-select: none; display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px;"
1448                            onclick="toggleCallbackUrlSection()">
1449                            <span style="font-weight: bold; color: #0066cc;">🚀 无法回源?试试快捷方式</span>
1450                            <span id="callbackUrlToggleIcon"
1451                                style="font-size: 14px; color: #666; transition: transform 0.3s ease;">▼</span>
1452                        </div>
1453                        <div id="callbackUrlSection" style="display: none;">
1454                            <div
1455                                style="background: #fff3cd; border: 1px solid #ffeaa7; border-radius: 6px; padding: 12px; margin-bottom: 12px;">
1456                                <div style="color: #856404; font-size: 14px; font-weight: bold; margin-bottom: 6px;">📚
1457                                    适用场景:</div>
1458                                <ul
1459                                    style="color: #856404; font-size: 13px; margin: 0; padding-left: 18px; line-height: 1.5;">
1460                                    <li>云服务器、VPS等非本地环境</li>
1461                                    <li>防火墙阻止了11451端口访问</li>
1462                                    <li>网络环境无法正常回源到localhost</li>
1463                                    <li>Docker容器内运行,端口映射问题</li>
1464                                </ul>
1465                            </div>
1466                            <div style="color: #666; font-size: 13px; margin-bottom: 12px; line-height: 1.6;">
1467                                <strong style="color: #0066cc;">🔍 什么是回调URL?</strong><br>
1468                                完成Google OAuth授权后,浏览器地址栏显示的完整URL,通常看起来像这样:<br>
1469                                <code
1470                                    style="background: #f1f3f4; padding: 2px 6px; border-radius: 3px; font-size: 12px; word-break: break-all;">
1471                                    http://localhost:11451/?state=abc123...&code=4/0AVMBsJ...&scope=email%20profile...
1472                                </code>
1473                            </div>
1474                            <div
1475                                style="background: #e7f3ff; border: 1px solid #b3d9ff; border-radius: 6px; padding: 10px; margin-bottom: 12px;">
1476                                <div style="color: #0066cc; font-size: 13px; font-weight: bold; margin-bottom: 4px;">📋
1477                                    使用步骤:</div>
1478                                <ol
1479                                    style="color: #0066cc; font-size: 12px; margin: 0; padding-left: 18px; line-height: 1.4;">
1480                                    <li>点击上方认证链接,完成Google授权</li>
1481                                    <li>授权成功后,复制浏览器地址栏的<strong>完整URL</strong></li>
1482                                    <li>粘贴到下方输入框,点击获取凭证即可</li>
1483                                </ol>
1484                            </div>
1485                            <div class="input-group">
1486                                <input type="url" id="callbackUrlInput"
1487                                    placeholder="粘贴完整的回调URL,例如:http://localhost:11451/?state=xxx&code=xxx&scope=xxx..."
1488                                    style="width: 100%; padding: 10px; border: 2px solid #ddd; border-radius: 4px; font-size: 13px;">
1489                            </div>
1490                            <button class="btn" style="margin-top: 10px;" onclick="processCallbackUrl()">
1491                                从回调URL获取凭证
1492                            </button>
1493                        </div>
1494                    </div>
1495
1496                    <button class="btn" id="getCredsBtn" onclick="getCredentials()">获取认证文件</button>
1497                </div>
1498
1499                <div id="credentialsSection" class="hidden">
1500                    <h3>认证文件内容:</h3>
1501                    <div class="credentials" id="credentialsContent"></div>
1502                </div>
1503            </div>
1504
1505            <!-- Antigravity 认证标签页 -->
1506            <div id="antigravityTab" class="tab-content">
1507                <div class="status info" style="margin-bottom: 20px;">
1508                    <strong>🚀 Antigravity 认证模式</strong>
1509                    <p style="margin: 10px 0;">
1510                        获取谷歌Antigravity 凭证
1511                    </p>
1512                </div>
1513
1514                <button class="btn" id="getAntigravityAuthBtn">获取 Antigravity 认证链接</button>
1515
1516                <div id="antigravityAuthUrlSection" class="hidden">
1517                    <h3>
1517Antigravity 认证链接:</h3>
1518                    <div class="auth-url">
1519                        <a id="antigravityAuthUrl" href="#" target="_blank">点击此链接进行认证</a>
1520                    </div>
1521                    <div class="status info">
1522                        <strong>使用说明:</strong>
1523                        <ol style="margin: 10px 0; padding-left: 20px;">
1524                            <li>点击上方认证链接,在新窗口中完成 Google 授权</li>
1525                            <li>授权成功后会跳转到 localhost 显示成功页面</li>
1526                            <li>关闭 OAuth 窗口,返回本页面</li>
1527                            <li>点击下方"获取凭证"按钮完成流程</li>
1528                        </ol>
1529                    </div>
1530
1531                    <!-- 快捷回调URL输入选项 -->
1532                    <div class="form-group"
1533                        style="margin: 20px 0; padding: 15px; border: 2px solid #e8f4fd; border-radius: 8px; background: #f8fcff;">
1534                        <div style="cursor: pointer; user-select: none; display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px;"
1535                            onclick="toggleAntigravityCallbackUrlSection()">
1536                            <span style="font-weight: bold; color: #0066cc;">🚀 无法回源?试试快捷方式</span>
1537                            <span id="antigravityCallbackUrlToggleIcon"
1538                                style="font-size: 14px; color: #666; transition: transform 0.3s ease;">▼</span>
1539                        </div>
1540                        <div id="antigravityCallbackUrlSection" style="display: none;">
1541                            <div
1542                                style="background: #fff3cd; border: 1px solid #ffeaa7; border-radius: 6px; padding: 12px; margin-bottom: 12px;">
1543                                <div style="color: #856404; font-size: 14px; font-weight: bold; margin-bottom: 6px;">📚
1544                                    适用场景:</div>
1545                                <ul
1546                                    style="color: #856404; font-size: 13px; margin: 0; padding-left: 18px; line-height: 1.5;">
1547                                    <li>云服务器、VPS等非本地环境</li>
1548                                    <li>防火墙阻止了11451端口访问</li>
1549                                    <li>网络环境无法正常回源到localhost</li>
1550                                    <li>Docker容器内运行,端口映射问题</li>
1551                                </ul>
1552                            </div>
1553                            <div style="color: #666; font-size: 13px; margin-bottom: 12px; line-height: 1.6;">
1554                                <strong style="color: #0066cc;">🔍 什么是回调URL?</strong><br>
1555                                完成Google OAuth授权后,浏览器地址栏显示的完整URL,通常看起来像这样:<br>
1556                                <code
1557                                    style="background: #f1f3f4; padding: 2px 6px; border-radius: 3px; font-size: 12px; word-break: break-all;">
1558                                    http://localhost:11451/?state=abc123...&code=4/0AVMBsJ...&scope=email%20profile...
1559                                </code>
1560                            </div>
1561                            <div
1562                                style="background: #e7f3ff; border: 1px solid #b3d9ff; border-radius: 6px; padding: 10px; margin-bottom: 12px;">
1563                                <div style="color: #0066cc; font-size: 13px; font-weight: bold; margin-bottom: 4px;">📋
1564                                    使用步骤:</div>
1565                                <ol
1566                                    style="color: #0066cc; font-size: 12px; margin: 0; padding-left: 18px; line-height: 1.4;">
1567                                    <li>点击上方认证链接,完成Google授权</li>
1568                                    <li>授权成功后,复制浏览器地址栏的<strong>完整URL</strong></li>
1569                                    <li>粘贴到下方输入框,点击获取凭证即可</li>
1570                                </ol>
1571                            </div>
1572                            <div class="input-group">
1573                                <input type="url" id="antigravityCallbackUrlInput"
1574                                    placeholder="粘贴完整的回调URL,例如:http://localhost:11451/?state=xxx&code=xxx&scope=xxx..."
1575                                    style="width: 100%; padding: 10px; border: 2px solid #ddd; border-radius: 4px; font-size: 13px;">
1576                            </div>
1577                            <button class="btn" style="margin-top: 10px;" onclick="processAntigravityCallbackUrl()">
1578                                从回调URL获取凭证
1579                            </button>
1580                        </div>
1581                    </div>
1582
1583                    <button class="btn" id="getAntigravityCredsBtn" onclick="getAntigravityCredentials()">获取 Antigravity
1584                        凭证</button>
1585
1586                    <div id="antigravityCredsSection" class="hidden">
1587                        <h3>
1587Antigravity 凭证内容:</h3>
1588                        <div class="credentials">
1589                            <pre id="antigravityCredsContent"></pre>
1590                        </div>
1591                        <button class="btn" onclick="downloadAntigravityCredentials()">下载凭证文件</button>
1592                    </div>
1593                </div>
1594            </div>
1595
1596            <!-- 批量上传标签页 -->
1597            <div id="uploadTab" class="tab-content">
1598                <h3>批量上传认证文件</h3>
1599                <p>支持批量上传 GCLI 和 Antigravity 认证文件</p>
1600
1601                <!-- GCLI凭证上传区域 -->
1602                <div
1603                    style="margin-bottom: 30px; padding: 20px; border: 2px solid #e1e4e8; border-radius: 8px; background: #f8f9fa;">
1604                    <h4 style="margin-top: 0; color: #007bff; border-bottom: 2px solid #007bff; padding-bottom: 10px;">
1605                        📤 GCLI 凭证批量上传</h4>
1606
1607                    <div class="upload-area" id="uploadArea" onclick="document.getElementById('fileInput').click()">
1608                        <p>点击选择文件或拖拽文件到此区域</p>
1609                        <p style="color: #666; font-size: 14px;">支持 .json 和 .zip 格式文件</p>
1610                        <p style="color: #888; font-size: 12px;">ZIP文件会自动解压提取其中的JSON凭证</p>
1611                    </div>
1612
1613                    <input type="file" id="fileInput" multiple accept=".json,.zip" style="display: none;"
1614                        onchange="handleFileSelect(event)" />
1615
1616                    <div id="fileListSection" class="hidden">
1617                        <h4>选择的文件:</h4>
1618                        <div class="file-list" id="fileList"></div>
1619                        <button class="btn" onclick="uploadFiles()">上传文件</button>
1620                        <button class="btn" onclick="clearFiles()">清空列表</button>
1621                    </div>
1622
1623                    <div id="uploadProgressSection" class="hidden">
1624                        <div class="upload-progress">
1625                            <h4>上传进度:</h4>
1626                            <div class="progress-bar">
1627                                <div class="progress-fill" id="progressFill" style="width: 0%"></div>
1628                            </div>
1629                            <p id="progressText">0%</p>
1630                        </div>
1631                    </div>
1632                </div>
1633
1634                <!-- Antigravity凭证上传区域 -->
1635                <div style="padding: 20px; border: 2px solid #e1e4e8; border-radius: 8px; background: #f8f9fa;">
1636                    <h4 style="margin-top: 0; color: #28a745; border-bottom: 2px solid #28a745; padding-bottom: 10px;">
1637                        📤 Antigravity 凭证批量上传</h4>
1638
1639                    <div class="upload-area" style="border-color: #28a745;"
1640                        onclick="document.getElementById('antigravityFileInput').click()"
1641                        ondragover="event.preventDefault(); this.style.borderColor='#28a745'; this.style.backgroundColor='#e7f9e7';"
1642                        ondragleave="this.style.borderColor='#ddd'; this.style.backgroundColor='#fafafa';"
1643                        ondrop="handleAntigravityFileDrop(event)">
1644                        <p>点击选择文件或拖拽文件到此区域</p>
1645                        <p style="color: #666; font-size: 14px;">支持 .json 和 .zip 格式文件</p>
1646                        <p style="color: #888; font-size: 12px;">ZIP文件会自动解压提取其中的JSON凭证</p>
1647                    </div>
1648
1649                    <input type="file" id="antigravityFileInput" multiple accept=".json,.zip" style="display: none;"
1650                        onchange="handleAntigravityFileSelect(event)" />
1651
1652                    <div id="antigravityFileListSection" class="hidden">
1653                        <h4>选择的文件:</h4>
1654                        <div class="file-list" id="antigravityFileList"></div>
1655                        <button class="btn" onclick="uploadAntigravityFiles()">上传文件</button>
1656                        <button class="btn" onclick="clearAntigravityFiles()">清空列表</button>
1657                    </div>
1658
1659                    <div id="antigravityUploadProgressSection" class="hidden">
1660                        <div class="upload-progress">
1661                            <h4>上传进度:</h4>
1662                            <div class="progress-bar">
1663                                <div class="progress-fill" id="antigravityProgressFill" style="width: 0%"></div>
1664                            </div>
1665                            <p id="antigravityProgressText">0%</p>
1666                        </div>
1667                    </div>
1668                </div>
1669            </div>
1670
1671            <!-- GCLI凭证管理标签页 -->
1672            <div id="manageTab" class="tab-content">
1673                <h3>GCLI凭证文件管理</h3>
1674                <p>管理所有GCLI认证文件,查看状态和执行操作</p>
1675                <div
1676                    style="background:#f0f7ff;border:1px solid #b8d4f0;border-radius:6px;padding:10px 14px;margin:8px 0;font-size:13px;">
1677                    <strong>📡 API地址(点击复制):</strong>
1678                    <table style="margin-top:6px;border-collapse:collapse;width:100%;">
1679                        <tr>
1680                            <td style="color:#666;width:90px;">OpenAI格式</td>
1681                            <td><code id="gcliOpenaiUrl" onclick="cpUrl(this)" title="点击复制"
1682                                    style="background:#e8f0fe;padding:2px 6px;border-radius:3px;
1682cursor:pointer;"></code>
1683                            </td>
1684                        </tr>
1685                        <tr>
1686                            <td style="color:#666;">Claude格式</td>
1687                            <td><code id="gcliClaudeUrl" onclick="cpUrl(this)" title="点击复制"
1688                                    style="background:#e8f0fe;padding:2px 6px;border-radius:3px;cursor:pointer;"></code>
1689                            </td>
1690                        </tr>
1691                        <tr>
1692                            <td style="color:#666;">Gemini格式</td>
1693                            <td><code id="gcliGeminiUrl" onclick="cpUrl(this)" title="点击复制"
1694                                    style="background:#e8f0fe;padding:2px 6px;border-radius:3px;cursor:pointer;"></code>
1695                            </td>
1696                        </tr>
1697                    </table>
1698                    
1698<script>
1699                        (function () { var o = window.location.origin; document.getElementById('gcliOpenaiUrl').textContent = o + '/v1'; document.getElementById('gcliClaudeUrl').textContent = o + '/v1'; document.getElementById('gcliGeminiUrl').textContent = o; })();
1700                        function cpUrl(el) { navigator.clipboard.writeText(el.textContent).then(function () { var s = el.style.background; el.style.background = '#b7f0b7'; setTimeout(function () { el.style.background = s; }, 800); }); }
1701                    </script>
1701
1702                </div>
1703
1704                <!-- 检验功能说明 -->
1705                <div class="status info" style="margin-bottom: 20px;">
1706                    <strong>💡 检验功能说明:</strong>
1707                    <p style="margin: 10px 0;">
1708                        点击每个凭证的"检验"按钮可以重新获取Project ID, 并查看账号的tier(free/pro/ultra)。<br>
1709                        <strong style="color: #0c5460;">✅ 检验成功可以恢复403错误</strong>,让凭证重新正常工作。<br>
1710                        建议在遇到403错误时使用此功能。
1711                    </p>
1712                    <strong>💡 设置预览功能说明:</strong>
1713                    <p style="margin: 10px 0;">
1714                        点击每个凭证的"设置预览"按钮可以配置Preview通道。<br>
1715                        <strong style="color: #0c5460;">✅ 设置预览可以解决部分凭证调用preview模型时404的问题</strong>。<br>
1716                        建议在调用gemini-3-pro-preview等模型遇到404错误时使用此功能。
1717                    </p>
1718                </div>
1719
1720                <!-- 状态统计 -->
1721                <div class="stats-container" id="statsContainer">
1722                    <div class="stat-item total">
1723                        <span class="stat-number" id="statTotal">0</span>
1724                        <span class="stat-label">总计</span>
1725                    </div>
1726                    <div class="stat-item normal">
1727                        <span class="stat-number" id="statNormal">0</span>
1728                        <span class="stat-label">正常</span>
1729                    </div>
1730                    <div class="stat-item disabled">
1731                        <span class="stat-number" id="statDisabled">0</span>
1732                        <span class="stat-label">禁用</span>
1733                    </div>
1734                </div>
1735
1736                <div class="manage-actions">
1737                    <button class="refresh-btn" onclick="refreshCredsStatus()">刷新状态</button>
1738                    <button class="download-all-btn" onclick="downloadAllCreds()">打包下载所有文件</button>
1739                </div>
1740
1741                <!-- 批量操作控件 -->
1742                <div class="batch-controls">
1743                    <h4 style="margin-top: 0; margin-bottom: 10px;">批量操作</h4>
1744                    <div class="batch-actions">
1745                        <div class="checkbox-container">
1746                            <input type="checkbox" id="selectAllCheckbox" class="select-all-checkbox"
1747                                onchange="toggleSelectAll()">
1748                            <label for="selectAllCheckbox">全选</label>
1749                        </div>
1750                        <span class="selected-count" id="selectedCount">已选择 0 项</span>
1751                        <button class="batch-btn batch-enable" id="batchEnableBtn" onclick="batchAction('enable')"
1752                            disabled>批量启用</button>
1753                        <button class="batch-btn batch-disable" id="batchDisableBtn" onclick="batchAction('disable')"
1754                            disabled>批量禁用</button>
1755                        <button class="batch-btn batch-delete" id="batchDeleteBtn" onclick="batchAction('delete')"
1756                            disabled>批量删除</button>
1757                        <button class="batch-btn" id="batchVerifyBtn" onclick="batchVerifyProjectIds()"
1758                            disabled>批量检验</button>
1759                        <button class="batch-btn" id="batchPreviewBtn" onclick="batchConfigurePreview()"
1760                            disabled>批量设置预览</button>
1761                        <button class="batch-btn batch-email" onclick="refreshAllEmails()">刷新所有邮箱</button>
1762                        <button class="batch-btn" onclick="deduplicateByEmail()">凭证一键去重</button>
1763                    </div>
1764                </div>
1765
1766                <!-- 筛选和分页控件 -->
1767                <div class="filter-container">
1768                    <label for="statusFilter">凭证状态:</label>
1769                    <select id="statusFilter" class="filter-select" onchange="applyStatusFilter()">
1770                        <option value="all">全部凭证</option>
1771                        <option value="enabled">仅启用</option>
1772                        <option value="disabled">仅禁用</option>
1773                    </select>
1774
1775                    <label for="errorCodeFilter" style="margin-left: 20px;">错误码:</label>
1776                    <select id="errorCodeFilter" class="filter-select" onchange="applyStatusFilter()">
1777                        <option value="all">全部</option>
1778                        <option value="none">无错误</option>
1779                        <option value="400">400</option>
1780                        <option value="403">403</option>
1781                        <option value="429">429</option>
1782                        <option value="500">500</option>
1783                    </select>
1784
1785                    <label for="cooldownFilter" style="margin-left: 20px;">冷却状态:</label>
1786                    <select id="cooldownFilter" class="filter-select" onchange="applyStatusFilter()">
1787                        <option value="all">全部</option>
1788                        <option value="in_cooldown">CD中</option>
1789                        <option value="no_cooldown">未CD</option>
1790                    </select>
1791
1792                    <label for="previewFilter" style="margin-left: 20px;">Preview:</label>
1793                    <select id="previewFilter" class="filter-select" onchange="applyStatusFilter()">
1794                        <option value="all">全部</option>
1795                        <option value="preview">支持</option>
1796                        <option value="no_preview">不支持</option>
1797                    </select>
1798
1799                    <label for="tierFilter" style="margin-left: 20px;">Tier:</label>
1800                    <select id="tierFilter" class="filter-select" onchange="applyStatusFilter()">
1801                        <option value="all">全部</option>
1802                        <option value="free">Free</option>
1803                        <option value="pro">Pro</option>
1804                        <option value="ultra">Ultra</option>
1805                    </select>
1806
1807                    <label for="pageSizeSelect" style="margin-left: 20px;">每页显示:</label>
1808                    <select id="pageSizeSelect" class="page-size-select" onchange="changePageSize()">
1809                        <option value="20">20</option>
1810                        <option value="50">50</option>
1811                        <option value="100">100</option>
1812                        <option value="200">200</option>
1813                        <option value="500">500</option>
1814                        <option value="1000">1000</option>
1815                    </select>
1816                </div>
1817
1818                <div id="credsListSection">
1819                    <div class="loading" id="credsLoading">正在加载凭证文件...</div>
1820                    <div id="credsList"></div>
1821
1822                    <!-- 分页控件 -->
1823                    <div class="pagination-container" id="paginationContainer" style="display: none;">
1824                        <button class="pagination-btn" id="prevPageBtn" onclick="changePage(-1)">上一页</button>
1825                        <div class="pagination-info" id="paginationInfo">第 1 页,共 1 页</div>
1826                        <button class="pagination-btn" id="nextPageBtn" onclick="changePage(1)">下一页</button>
1827                    </div>
1828                </div>
1829            </div>
1830
1831            <!-- Antigravity 凭证管理标签页 -->
1832            <div id="antigravity-manageTab" class="tab-content">
1833                <h3>
1833Antigravity凭证文件管理</h3>
1834                <p>管理所有Antigravity认证文件,查看状态和执行操作</p>
1835                <div
1836                    style="background:#f0f7ff;border:1px solid #b8d4f0;border-radius:6px;padding:10px 14px;margin:8px 0;font-size:13px;">
1837                    <strong>📡 API地址(点击复制):</strong>
1838                    <table style="margin-top:6px;border-collapse:collapse;width:100%;">
1839                        <tr>
1840                            <td style="color:#666;width:90px;">OpenAI格式</td>
1841                            <td><code id="antOpenaiUrl" onclick="cpUrl(this)" title="点击复制"
1842                                    style="background:#e8f0fe;padding:2px 6px;border-radius:3px;cursor:pointer;"></code>
1843                            </td>
1844                        </tr>
1845                        <tr>
1846                            <td style="color:#666;">Claude格式</td>
1847                            <td><code id="antClaudeUrl" onclick="cpUrl(this)" title="点击复制"
1848                                    style="background:#e8f0fe;padding:2px 6px;border-radius:3px;cursor:pointer;"></code>
1849                            </td>
1850                        </tr>
1851                        <tr>
1852                            <td style="color:#666;">Gemini格式</td>
1853                            <td><code id="antGeminiUrl" onclick="cpUrl(this)" title="点击复制"
1854                                    style="background:#e8f0fe;padding:2px 6px;border-radius:3px;cursor:pointer;"></code>
1855                            </td>
1856                        </tr>
1857                    </table>
1858                    
1858<script>
1859                        (function () { var o2 = window.location.origin; document.getElementById('antOpenaiUrl').textContent = o2 + '/antigravity/v1'; document.getElementById('antClaudeUrl').textContent = o2 + '/antigravity/v1'; document.getElementById('antGeminiUrl').textContent = o2 + '/antigravity'; })();
1860                    </script>
1860
1861                </div>
1862
1863                <!-- 检验功能说明 -->
1864                <div class="status info" style="margin-bottom: 20px;">
1865                    <strong>💡 检验功能说明:</strong>
1866                    <p style="margin: 10px 0;">
1867                        点击每个凭证的"检验"按钮可以重新获取Project ID, 并查看账号的tier(free/pro/ultra)。<br>
1868                        <strong style="color: #0c5460;">✅ 检验成功可以恢复403错误</strong>,让凭证重新正常工作。<br>
1869                        建议在遇到403错误时使用此功能。
1870                    </p>
1871                </div>
1872
1873                <!-- 状态统计 -->
1874                <div class="stats-container" id="antigravityStatsContainer">
1875                    <div class="stat-item total">
1876                        <span class="stat-number" id="antigravityStatTotal">0</span>
1877                        <span class="stat-label">总计</span>
1878                    </div>
1879                    <div class="stat-item normal">
1880                        <span class="stat-number" id="antigravityStatNormal">0</span>
1881                        <span class="stat-label">正常</span>
1882                    </div>
1883                    <div class="stat-item disabled">
1884                        <span class="stat-number" id="antigravityStatDisabled">0</span>
1885                        <span class="stat-label">禁用</span>
1886                    </div>
1887                </div>
1888
1889                <div class="manage-actions">
1890                    <button class="refresh-btn" onclick="refreshAntigravityCredsList()">刷新状态</button>
1891                    <button class="download-all-btn" onclick="downloadAllAntigravityCreds()">打包下载所有文件</button>
1892                </div>
1893
1894                <!-- 批量操作控件 -->
1895                <div class="batch-controls">
1896                    <h4 style="margin-top: 0; margin-bottom: 10px;">批量操作</h4>
1897                    <div class="batch-actions">
1898                        <div class="checkbox-container">
1899                            <input type="checkbox" id="selectAllAntigravityCheckbox" class="select-all-checkbox"
1900                                onchange="toggleSelectAllAntigravity()">
1901                            <label for="selectAllAntigravityCheckbox">全选</label>
1902                        </div>
1903                        <span class="selected-count" id="antigravitySelectedCount">已选择 0 项</span>
1904                        <button class="batch-btn batch-enable" id="antigravityBatchEnableBtn"
1905                            onclick="batchAntigravityAction('enable')" disabled>批量启用</button>
1906                        <button class="batch-btn batch-disable" id="antigravityBatchDisableBtn"
1907                            onclick="batchAntigravityAction('disable')" disabled>批量禁用</button>
1908                        <button class="batch-btn batch-delete" id="antigravityBatchDeleteBtn"
1909                            onclick="batchAntigravityAction('delete')" disabled>批量删除</button>
1910                        <button class="batch-btn" id="antigravityBatchEnableCreditBtn"
1911                            onclick="batchAntigravityAction('enable_credit')" disabled>批量开启积分</button>
1912                        <button class="batch-btn" id="antigravityBatchDisableCreditBtn"
1913                            onclick="batchAntigravityAction('disable_credit')" disabled>批量关闭积分</button>
1914                        <button class="batch-btn" id="antigravityBatchVerifyBtn"
1915                            onclick="batchVerifyAntigravityProjectIds()" disabled>批量检验</button>
1916                        <button class="batch-btn batch-email" onclick="refreshAllAntigravityEmails()">刷新所有邮箱</button>
1917                        <button class="batch-btn" onclick="deduplicateAntigravityByEmail()">凭证一键去重</button>
1918                    </div>
1919                </div>
1920
1921                <!-- 筛选和分页控件 -->
1922                <div class="filter-container">
1923                    <label for="antigravityStatusFilter">凭证状态:</label>
1924                    <select id="antigravityStatusFilter" class="filter-select"
1925                        onchange="applyAntigravityStatusFilter()">
1926                        <option value="all">全部凭证</option>
1927                        <option value="enabled">仅启用</option>
1928                        <option value="disabled">仅禁用</option>
1929                    </select>
1930
1931                    <label for="antigravityErrorCodeFilter" style="margin-left: 20px;">错误码:</label>
1932                    <select id="antigravityErrorCodeFilter" class="filter-select"
1933                        onchange="applyAntigravityStatusFilter()">
1934                        <option value="all">全部</option>
1935                        <option value="none">无错误</option>
1936                        <option value="400">400</option>
1937                        <option value="403">403</option>
1938                        <option value="429">429</option>
1939                        <option value="500">500</option>
1940                    </select>
1941
1942                    <label for="antigravityCooldownFilter" style="margin-left: 20px;">冷却状态:</label>
1943                    <select id="antigravityCooldownFilter" class="filter-select"
1944                        onchange="applyAntigravityStatusFilter()">
1945                        <option value="all">全部</option>
1946                        <option value="in_cooldown">CD中</option>
1947                        <option value="no_cooldown">未CD</option>
1948                    </select>
1949
1950                    <label for="antigravityTierFilter" style="margin-left: 20px;">Tier:</label>
1951                    <select id="antigravityTierFilter" class="filter-select" onchange="applyAntigravityStatusFilter()">
1952                        <option value="all">全部</option>
1953                        <option value="free">Free</option>
1954                        <option value="pro">Pro</option>
1955                        <option value="ultra">Ultra</option>
1956                    </select>
1957
1958                    <label for="antigravityPageSizeSelect" style="margin-left: 20px;">每页显示:</label>
1959                    <select id="antigravityPageSizeSelect" class="page-size-select"
1960                        onchange="changeAntigravityPageSize()">
1961                        <option value="20">20</option>
1962                        <option value="50">50</option>
1963                        <option value="100">100</option>
1964                        <option value="200">200</option>
1965                        <option value="500">500</option>
1966                        <option value="1000">1000</option>
1967                    </select>
1968                </div>
1969
1970                <div id="antigravityCredsListSection">
1971                    <div class="loading" id="antigravityCredsLoading">正在加载凭证文件...</div>
1972                    <div id="antigravityCredsList"></div>
1973
1974                    <!-- 分页控件 -->
1975                    <div class="pagination-container" id="antigravityPaginationContainer" style="display: none;">
1976                        <button class="pagination-btn" id="antigravityPrevPageBtn"
1977                            onclick="changeAntigravityPage(-1)">上一页</button>
1978                        <div class="pagination-info" id="antigravityPaginationInfo">第 1 页,共 1 页</div>
1979                        <button class="pagination-btn" id="antigravityNextPageBtn"
1980                            onclick="changeAntigravityPage(1)">下一页</button>
1981                    </div>
1982                </div>
1983            </div>
1984
1985            <!-- 配置管理标签页 -->
1986            <div id="configTab" class="tab-content">
1987                <h3>配置管理</h3>
1988                <p>管理系统配置参数,修改后立即生效</p>
1989
1990                <div class="manage-actions">
1991                    <button class="refresh-btn" onclick="loadConfig()">刷新配置</button>
1992                    <button class="btn" onclick="saveConfig()">保存配置</button>
1993                </div>
1994
1995                <div id="configSection">
1996                    <div class="loading" id="configLoading">正在加载配置...</div>
1997                    <div id="configForm" class="hidden">
1998                        <div class="config-group">
1999                            <h4>服务器配置</h4>
2000
2001                            <div class="form-group">
2002                                <label for="host">服务器主机地址:</label>
2003                                <input type="text" id="host" class="config-input"
2004                                    placeholder="例如: 0.0.0.0, 127.0.0.1" />
2005                                <small class="config-note">服务器监听的主机地址,0.0.0.0表示监听所有接口</small>
2006                            </div>
2007
2008                            <div class="form-group">
2009                                <label for="port">服务器端口:</label>
2010                                <input type="number" id="port" class="config-input" min="1" max="65535"
2011                                    placeholder="7861" />
2012                                <small class="config-note">服务器监听的端口号,修改后需要重启服务器</small>
2013                            </div>
2014
2015                            <div class="form-group">
2016                                <label for="configApiPassword">API访问密码:</label>
2017                                <input type="text" id="configApiPassword" class="config-input" placeholder="pwd" />
2018                                <small class="config-note">聊天API访问密码,用于OpenAI和Gemini API端点的认证</small>
2019                            </div>
2020
2021                            <div class="form-group">
2022                                <label for="configPanelPassword">控制面板密码:</label>
2023                                <input type="text" id="configPanelPassword" class="config-input" placeholder="pwd" />
2024                                <small class="config-note">控制面板访问密码,用于web界面登录认证</small>
2025                            </div>
2026
2027                            <div class="form-group">
2028                                <label for="configPassword">通用密码:</label>
2029                                <input type="text" id="configPassword" class="config-input" placeholder="pwd" />
2030                                <small class="config-note">(兼容性保留)设置后将覆盖上述两个密码,留空则使用分开的密码设置</small>
2031                            </div>
2032                        </div>
2033
2034                        <div class="config-group">
2035                            <h4>基础配置</h4>
2036
2037                            <div class="form-group">
2038                                <label for="credentialsDir">凭证目录路径:</label>
2039                                <input type="text" id="credentialsDir" class="config-input" />
2040                                <small class="config-note">存储认证文件的目录路径</small>
2041                            </div>
2042
2043                            <div class="form-group">
2044                                <label for="proxy">代理设置:</label>
2045                                <input type="text" id="proxy" class="config-input"
2046                                    placeholder="例如: http://proxy:11451 或 socks5://proxy:1080" />
2047                                <small class="config-note">HTTP/HTTPS/SOCKS5Endpoint,留空表示不使用代理</small>
2048                            </div>
2049                        </div>
2050
2051                        <div class="config-group">
2052                            <h4>端点配置</h4>
2053
2054                            <!-- 快速配置按钮 -->
2055                            <div class="form-group">
2056                                <div style="display: flex; gap: 10px; margin-bottom: 15px; flex-wrap: wrap;">
2057                                    <button type="button" class="btn" onclick="useMirrorUrls()"
2058                                        style="font-size: 14px;">
2059                                        🚀 一键使用镜像网址
2060                                    </button>
2061                                    <button type="button" class="btn" onclick="restoreOfficialUrls()"
2062                                        style="font-size: 14px;">
2063                                        🔄 还原官方端点
2064                                    </button>
2065                                </div>
2066                                <small class="config-note">镜像网址主要解决墙内无法访问官方端点的问题,部分地区可能无法使用</small>
2067                            </div>
2068
2069                            <div class="form-group">
2070                                <label for="codeAssistEndpoint">Code Assist Endpoint:</label>
2071                                <input type="text" id="codeAssistEndpoint" class="config-input" />
2072                                <small class="config-note">Google Cloud Code Assist API端点地址</small>
2073                            </div>
2074                            <div class="form-group">
2075                                <label for="oauthProxyUrl">OAuth Endpoint:</label>
2076                                <input type="text" id="oauthProxyUrl" class="config-input"
2077                                    placeholder="https://oauth2.googleapis.com" />
2078                                <small class="config-note">Google OAuth2 API端点地址,用于token获取和刷新</small>
2079                            </div>
2080                            <div class="form-group">
2081                                <label for="googleapisProxyUrl">Google APIs Endpoint:</label>
2082                                <input type="text" id="googleapisProxyUrl" class="config-input"
2083                                    placeholder="https://www.googleapis.com" />
2084                                <small class="config-note">Google APIs API端点地址,用于API服务调用</small>
2085                            </div>
2086                            <div class="form-group">
2087                                <label for="resourceManagerApiUrl">Resource Manager API Endpoint:</label>
2088                                <input type="text" id="resourceManagerApiUrl" class="config-input"
2089                                    placeholder="https://cloudresourcemanager.googleapis.com" />
2090                                <small class="config-note">Google Cloud Resource Manager API端点地址,用于项目管理</small>
2091                            </div>
2092                            <div class="form-group">
2093                                <label for="serviceUsageApiUrl">Service Usage API Endpoint:</label>
2094                                <input type="text" id="serviceUsageApiUrl" class="config-input"
2095                                    placeholder="https://serviceusage.googleapis.com" />
2096                                <small class="config-note">Google Cloud Service Usage API端点地址,用于服务启用管理</small>
2097                            </div>
2098                            <div class="form-group">
2099                                <label for="antigravityApiUrl">Antigravity API Endpoint:</label>
2100                                <input type="text" id="antigravityApiUrl" class="config-input"
2101                                    placeholder="https://daily-cloudcode-pa.googleapis.com" />
2102                                <small class="config-note">Google Antigravity API端点地址,用于反重力模式</small>
2103                            </div>
2104                        </div>
2105
2106                        <div class="config-group">
2107                            <h4>自动封禁配置</h4>
2108
2109                            <div class="form-group">
2110                                <label>
2111                                    <input type="checkbox" id="autoBanEnabled" class="config-checkbox" />
2112                                    启用自动封禁
2113                                </label>
2114                                <small class="config-note">遇到指定错误码时自动禁用凭证</small>
2115                            </div>
2116
2117                            <div class="form-group">
2118                                <label for="autoBanErrorCodes">自动封禁错误码:</label>
2119                                <input type="text" id="autoBanErrorCodes" class="config-input"
2120                                    placeholder="例如: 400,403" />
2121                                <small class="config-note">用逗号分隔的错误码列表</small>
2122                            </div>
2123                        </div>
2124
2125                        <div class="config-group">
2126                            <h4>重试配置</h4>
2127
2128                            <div class="form-group">
2129                                <label>
2130                                    <input type="checkbox" id="retry429Enabled" class="config-checkbox" />
2131                                    启用错误重试
2132                                </label>
2133                                <small class="config-note">遇到错误时自动重试</small>
2134                            </div>
2135
2136                            <div class="form-group">
2137                                <label for="retry429MaxRetries">错误重试次数:</label>
2138                                <input type="number" id="retry429MaxRetries" class="config-input" min="1" max="50" />
2139                                <small class="config-note">遇到错误时的最大重试次数</small>
2140                            </div>
2141
2142                            <div class="form-group">
2143                                <label for="retry429Interval">错误重试间隔(秒):</label>
2144                                <input type="number" id="retry429Interval" class="config-input" min="0.01" max="10"
2145                                    step="0.01" />
2146                                <small class="config-note">遇到错误时每两次重试间的等待时间</small>
2147                            </div>
2148                        </div>
2149
2150
2151                        <div class="config-group">
2152                            <h4>兼容性配置</h4>
2153
2154                            <div class="form-group">
2155                                <label>
2156                                    <input type="checkbox" id="compatibilityModeEnabled" class="config-checkbox" />
2157                                    启用兼容性模式
2158                                </label>
2159                                <small class="config-note">启用后所有system消息全部转换成user,停用system_instructions <span
2160                                        style="color: #28a745;">✓ 支持热更新</span></small>
2161                                <div class="config-info"
2162                                    style="background-color: #fff3cd; border: 1px solid #ffc107; color: #856404;">
2163                                    <strong>⚠️ 注意:</strong>该选项可能会降低模型理解能力,但是能避免流式空回的情况。
2164                                    <br><strong>适用场景:</strong>当遇到流式传输时模型不返回内容或返回空响应时启用此选项。
2165                                </div>
2166                            </div>
2167
2168                            <div class="form-group">
2169                                <label>
2170                                    <input type="checkbox" id="returnThoughtsToFrontend" class="config-checkbox" />
2171                                    返回思维链到前端
2172                                </label>
2173                                <small class="config-note">启用后,模型的思维链会在响应中返回;禁用后,思维链会被过滤掉 <span
2174                                        style="color: #28a745;">✓ 支持热更新</span></small>
2175                                <div class="config-info"
2176                                    style="background-color: #e3f2fd; border: 1px solid #2196f3; color: #0d47a1;">
2177                                    <strong>💭 说明:</strong>某些模型(如Gemini 2.0
2178                                    Pro)支持thinking模式,会在生成回答前先输出思考过程。启用后可以看到模型的思考过程;禁用后只显示最终回答,让输出更简洁。
2179                                </div>
2180                            </div>
2181
2182                            <div class="form-group">
2183                                <label>
2184                                    <input type="checkbox" id="antigravityStream2nostream" class="config-checkbox" />
2185                                    Antigravity流式转非流式
2186                                </label>
2187                                <small class="config-note">启用后,非流式请求将使用流式API并收集为完整响应 <span style="color: #28a745;">✓
2188                                        支持热更新</span></small>
2189                                <div class="config-info"
2190                                    style="background-color: #f3e5f5; border: 1px solid #9c27b0; color: #4a148c;">
2191                                    <strong>🔄
2192                                        说明:</strong>针对Antigravity模式的优化选项。启用后,即使客户端请求非流式响应,后端也会使用流式API获取数据并收集完整后再返回。
2193                                    <br><strong>适用场景:</strong>某些情况下流式API比非流式API更稳定,启用此选项可以提高响应质量。
2194                                    <br><strong>默认:</strong>已启用
2195                                </div>
2196                            </div>
2197
2198                            <div class="form-group">
2199                                <label>
2200                                    <input type="checkbox" id="antigravitySwitchCredentialEnabled" class="config-checkbox" />
2201                                    Antigravity切换凭证
2202                                </label>
2203                                <small class="config-note">启用后重试时切换凭证;禁用时保持当前凭证,直到该凭证对当前模型进入CD或被禁用 <span
2204                                        style="color: #28a745;">✓ 支持热更新</span></small>
2205                                <div class="config-info"
2206                                    style="background-color: #e8f5e9; border: 1px solid #66bb6a; color: #1b5e20;">
2207                                    <strong>✅ 说明:</strong>默认关闭,便于连续使用同一凭证;当发生模型CD或自动禁用时仍会切换。
2208                                </div>
2209                            </div>
2210                        </div>
2211
2212                        <div class="config-group">
2213                            <h4>抗截断配置</h4>
2214
2215                            <div class="form-group">
2216                                <label for="antiTruncationMaxAttempts">抗截断最大重试次数:</label>
2217                                <input type="number" id="antiTruncationMaxAttempts" class="config-input" min="1"
2218                                    max="10" />
2219                                <small class="config-note">当检测到输出截断时的最大续传尝试次数</small>
2220                            </div>
2221
2222                            <div class="form-group">
2223                                <div class="config-info">
2224                                    <strong>注意:</strong>抗截断功能现在通过模型名控制:
2225                                    <ul style="margin: 5px 0; padding-left: 20px;">
2226                                        <li>选择带有 "-流式抗截断" 后缀的模型即可启用</li>
2227                                        <li>该功能仅在流式传输时生效</li>
2228                                        <li>例如: "gemini-2.5-pro-流式抗截断"</li>
2229                                    </ul>
2230                                </div>
2231                            </div>
2232                        </div>
2233
2234                        <div class="config-group">
2235                            <h4>保活配置</h4>
2236
2237                            <div class="form-group">
2238                                <label for="keepaliveUrl">保活 URL:</label>
2239                                <input type="text" id="keepaliveUrl" class="config-input"
2240                                    placeholder="留空则不启用,例如: https://your-app.example.com/keepalive" />
2241                                <small class="config-note">配置后服务会定期向该 URL 发送 GET 请求以保持在线;留空则禁用保活 <span
2242                                        style="color: #28a745;">✓ 支持热更新</span></small>
2243                                <button type="button" onclick="autoSetKeepaliveUrl()"
2244                                    style="margin-top:6px; padding:4px 12px; font-size:13px; cursor:pointer;">一键设置保活</button>
2245                            </div>
2246
2247                            <div class="form-group">
2248                                <label for="keepaliveInterval">保活间隔 (秒):</label>
2249                                <input type="number" id="keepaliveInterval" class="config-input" min="5" max="86400" />
2250                                <small class="config-note">两次保活请求之间的等待时间,范围 5 - 86400 秒,默认 60 <span
2251                                        style="color: #28a745;">✓ 支持热更新</span></small>
2252                            </div>
2253                        </div>
2254
2255                        <div class="config-group">
2256                            <h4>配置热更新说明</h4>
2257
2258                            <div class="form-group">
2259                                <div class="config-info"
2260                                    style="background-color: #d4edda; border: 1px solid #c3e6cb; color: #155724;">
2261                                    <strong>🔥 热更新配置(立即生效):</strong>
2262                                    <ul style="margin: 8px 0; padding-left: 20px; color: #212529;">
2263                                        <li><strong>网络配置:</strong>代理设置、端点配置、HTTP超时时间、最大连接数</li>
2264                                        <li><strong>API配置:</strong>凭证轮换次数、错误重试设置、自动封禁配置</li>
2265                                        <li><strong>密码配置:</strong>API密码、控制面板密码、通用密码</li>
2266                                        <li><strong>功能配置:</strong>抗截断最大重试次数</li>
2267                                    </ul>
2268                                </div>
2269                            </div>
2270
2271                            <div class="form-group">
2272                                <div class="config-info"
2273                                    style="background-color: #fff3cd; border: 1px solid #ffc107; color: #856404;">
2274                                    <strong>🔄 需要重启的配置:</strong>
2275                                    <ul style="margin: 8px 0; padding-left: 20px; color: #212529;">
2276                                        <li><strong>服务器配置:</strong>主机地址、端口号</li>
2277                                        <li><strong>目录配置:</strong>凭证目录路径、Code Assist端点</li>
2278                                    </ul>
2279                                </div>
2280                            </div>
2281
2282                        </div>
2283                    </div>
2284                </div>
2285            </div>
2286
2287            <!-- 实时日志标签页 -->
2288            <div id="logsTab" class="tab-content">
2289                <h3>实时日志</h3>
2290                <p>查看系统实时日志输出,支持日志筛选和自动滚动</p>
2291
2292                <div class="manage-actions">
2293                    <button class="refresh-btn" onclick="connectWebSocket()">连接日志流</button>
2294                    <button class="btn" onclick="disconnectWebSocket()">断开连接</button>
2295                    <button class="btn" onclick="downloadLogs()">下载日志</button>
2296                    <button class="btn" onclick="clearLogs()">清空日志</button>
2297                </div>
2298
2299                <div class="filter-container">
2300                    <label for="logLevelFilter">日志级别筛选:</label>
2301                    <select id="logLevelFilter" class="filter-select" onchange="filterLogs()">
2302                        <option value="all">全部</option>
2303                        <option value="ERROR">错误</option>
2304                        <option value="WARNING">
2304警告</option>
2305                        <option value="INFO">信息</option>
2306                        <option value="DEBUG">调试</option>
2307                    </select>
2308
2309                    <label>
2310                        <input type="checkbox" id="autoScroll" checked> 自动滚动到底部
2311                    </label>
2312                </div>
2313
2314                <div id="logConnectionStatus" class="status info">
2315                    <strong>连接状态:</strong> <span id="connectionStatusText">未连接</span>
2316                </div>
2317
2318                <div id="logContainer"
2319                    style="background-color: #1e1e1e; color: #ffffff; font-family: 'Courier New', monospace; font-size: 12px; height: 600px; overflow-y: auto; border: 1px solid #333; border-radius: 5px; padding: 15px; white-space: pre-wrap; word-break: break-all;">
2320                    <div id="logContent">等待连接日志流...</div>
2321                </div>
2322            </div>
2323
2324            <!-- 项目信息标签页 -->
2325            <div id="aboutTab" class="tab-content">
2326                <h3>项目信息</h3>
2327                <p>关于GCLI2API项目的详细信息和支持方式</p>
2328
2329                <!-- 项目介绍 -->
2330                <div
2331                    style="background-color: #f8f9fa; padding: 20px; border-radius: 10px; margin: 20px 0; border-left: 4px solid #007bff;">
2332                    <h4 style="margin-top: 0; color: #007bff;">📋 项目简介</h4>
2333                    <p style="margin: 10px 0; line-height: 1.6; color: #495057;">
2334                        GCLI2API是一个将Google Gemini API转换为OpenAI 和GEMINI API格式的代理工具,支持多账户管理、自动轮换、实时日志监控等功能。
2335                    </p>
2336                    <div style="margin: 15px 0;">
2337                        <p style="margin: 5px 0;"><strong>🔗 项目地址:</strong> <a
2338                                href="https://github.com/su-kaka/gcli2api" target="_blank"
2339                                style="color: #007bff; text-decoration: none;">GitHub - su-kaka/gcli2api</a></p>
2340                        <p style="margin: 5px 0;"><strong>⚠️ 使用声明:</strong> <span
2341                                style="color: #dc3545; font-weight: 500;">禁止商业用途和倒卖 - 仅供学习使用</span></p>
2342                    </div>
2343                </div>
2344
2345                <!-- 功能特性 -->
2346                <div
2347                    style="background-color: #e7f3ff; padding: 20px; border-radius: 10px; margin: 20px 0; border-left: 4px solid #17a2b8;">
2348                    <h4 style="margin-top: 0; color: #17a2b8;">✨ 主要功能</h4>
2349                    <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 15px;">
2350                        <div>
2351                            <p><strong>🔄 多账户管理:</strong> 支持批量上传和管理多个Google账户</p>
2352                            <p><strong>⚡ 自动轮换:</strong> 智能轮换账户,避免单账户限额</p>
2353                            <p><strong>📊 实时监控:</strong> 使用统计、错误监控、实时日志</p>
2354                        </div>
2355                        <div>
2356                            <p><strong>🛡️ 安全可靠:</strong> OAuth2认证、自动封禁异常账户</p>
2357                            <p><strong>🎛️ 配置灵活:</strong> 支持热更新配置、代理设置</p>
2358                            <p><strong>📱 界面友好:</strong> 响应式设计、移动端适配</p>
2359                        </div>
2360                    </div>
2361                </div>
2362
2363                <!-- 交流群 -->
2364                <div
2365                    style="background-color: #e7f3ff; padding: 20px; border-radius: 10px; margin: 20px 0; border-left: 4px solid #4285f4; text-align: center;">
2366                    <h4 style="margin-top: 0; color: #1976d2;">💬 交流群</h4>
2367                    <div style="color: #1565c0; line-height: 1.6;">
2368                        <p>欢迎加入 QQ 群交流讨论!</p>
2369                        <p style="font-size: 18px; font-weight: bold; color: #4285f4;">QQ 群号:1083250744</p>
2370                    </div>
2371                    <div
2372                        style="display: inline-block; background: white; padding: 15px; border-radius: 12px; box-shadow: 0 2px 15px rgba(0,0,0,0.1); margin-top: 10px;">
2373                        <img src="docs/qq群.jpg" alt="QQ群二维码"
2374                            style="width: 200px; height: 200px; border-radius: 8px; display: block;">
2375                        <p
2376                            style="color: #666; margin: 10px 0 0 0; font-size: 13px; font-weight: 600; text-align: center;">
2377                            扫码加入QQ群</p>
2378                    </div>
2379                </div>
2380
2381                <!-- 联系和反馈 -->
2382                <div
2383                    style="background-color: #d1ecf1; padding: 20px; border-radius: 10px; margin: 20px 0; border-left: 4px solid #bee5eb;">
2384                    <h4 style="margin-top: 0; color: #0c5460;">📞 联系我们</h4>
2385                    <div style="color: #0c5460; line-height: 1.6;">
2386                        <p>• <strong>问题反馈:</strong> 通过GitHub Issues提交问题和建议</p>
2387                        <p>• <strong>功能请求:</strong> 在GitHub Discussions中讨论新功能</p>
2388                        <p>• <strong>代码贡献:</strong> 欢迎提交Pull Request改进项目</p>
2389                        <p>• <strong>文档完善:</strong> 帮助改进项目文档和使用指南</p>
2390                    </div>
2391                </div>
2392            </div>
2393
2394            <div id="statusSection"></div>
2395
2396            <!-- 项目信息 -->
2397            <div
2398                style="background-color: #f8f9fa; border: 1px solid #dee2e6; border-radius: 8px; padding: 12px; margin-top: 30px; text-align: center; border-left: 4px solid #007bff;">
2399                <p style="margin: 5px 0; font-size: 14px; color: #495057;">GitHub: <a
2400                        href="https://github.com/su-kaka/gcli2api" target="_blank"
2401                        style="color: #007bff; text-decoration: none;">https://github.com/su-kaka/gcli2api</a></p>
2402                <p style="margin: 5px 0; font-size: 14px; color: #dc3545; font-weight: 500;">⚠️ 禁止商业用途和倒卖 - 仅供学习使用 ⚠️
2403                </p>
2404            </div>
2405        </div>
2406    </div>
2407
2408    <!-- 引入公共JavaScript模块 -->
2409    
2409<script src="./front/common.js"></script>
2409
2410
2411</body>
2412
2413</html>

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.