44< head >
55 < meta charset ="UTF-8 ">
66 < meta name ="viewport " content ="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no ">
7- < title > Kiro API Proxy </ title >
7+ < title > Kiro-Go </ title >
88 < style >
99 * {
1010 box-sizing : border-box;
306306 flex-shrink : 0 ;
307307 }
308308
309+ .switch input {
310+ opacity : 0 ;
311+ width : 0 ;
312+ height : 0 ;
313+ position : absolute;
314+ }
315+
309316 .slider {
310317 position : absolute;
311318 cursor : pointer;
831838 </ div >
832839 < h1 class ="logo "> < svg viewBox ="0 0 24 24 " fill ="none " stroke ="currentColor " stroke-width ="2 ">
833840 < path d ="M13 2L3 14h9l-1 8 10-12h-9l1-8z " />
834- </ svg > Kiro API Proxy </ h1 >
841+ </ svg > Kiro-Go </ h1 >
835842 < p data-i18n ="login.subtitle "> </ p >
836843 < div class ="form-group ">
837844 < label data-i18n ="login.password "> </ label >
@@ -847,14 +854,15 @@ <h1 class="logo"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stro
847854 < div class ="header ">
848855 < h1 class ="logo "> < svg viewBox ="0 0 24 24 " fill ="none " stroke ="currentColor " stroke-width ="2 ">
849856 < path d ="M13 2L3 14h9l-1 8 10-12h-9l1-8z " />
850- </ svg > Kiro API Proxy </ h1 >
857+ </ svg > Kiro-Go </ h1 >
851858 < div class ="header-right ">
852859 < div class ="lang-switch ">
853860 < button class ="lang-btn " data-lang ="zh " onclick ="setLang('zh') "> 中文</ button >
854861 < button class ="lang-btn " data-lang ="en " onclick ="setLang('en') "> EN</ button >
855862 </ div >
856863 < span class ="badge badge-success " id ="statusBadge " data-i18n ="status.running "> </ span >
857864 < span class ="badge badge-info " id ="versionBadge " style ="cursor:pointer " onclick ="checkUpdate(true) "> </ span >
865+ < button class ="btn btn-sm btn-danger " onclick ="logout() " data-i18n ="common.logout " style ="padding:4px 12px;font-size:12px "> </ button >
858866 </ div >
859867 </ div >
860868 < div class ="stats-grid ">
@@ -893,13 +901,13 @@ <h1 class="logo"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stro
893901 < div class ="card-header ">
894902 < span class ="card-title " data-i18n ="accounts.title "> </ span >
895903 < div class ="card-actions ">
896- < label class ="privacy-toggle " style ="display:flex;align-items:center;gap:8px;cursor:pointer;user-select:none ">
904+ < div class ="privacy-toggle " style ="display:flex;align-items:center;gap:8px;cursor:pointer;user-select:none ">
897905 < span style ="font-size:13px;color:#374151;font-weight:500 " data-i18n ="privacy.label "> </ span >
898906 < label class ="switch " style ="margin:0 ">
899907 < input type ="checkbox " id ="privacyModeToggle " checked onchange ="togglePrivacyMode() ">
900908 < span class ="slider "> </ span >
901909 </ label >
902- </ label >
910+ </ div >
903911 < button class ="btn btn-secondary btn-sm " onclick ="showExportModal() " data-i18n ="accounts.export "> </ button >
904912 < button class ="btn btn-primary btn-sm " onclick ="showModal('add') " data-i18n ="accounts.add "> </ button >
905913 </ div >
@@ -986,6 +994,10 @@ <h1 class="logo"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stro
986994 < p style ="margin:14px 0 10px;font-weight:500;font-size:14px " data-i18n ="api.modelList "> </ p >
987995 < div class ="endpoint "> < span id ="modelsEndpoint "> </ span > < button class ="btn btn-sm btn-secondary "
988996 onclick ="copy('modelsEndpoint') " data-i18n ="common.copy "> </ button > </ div >
997+ < p style ="margin:14px 0 10px;font-weight:500;font-size:14px " data-i18n ="api.stats "> </ p >
998+ < div class ="endpoint "> < span id ="statsEndpoint "> </ span > < button class ="btn btn-sm btn-secondary "
999+ onclick ="copy('statsEndpoint') " data-i18n ="common.copy "> </ button > </ div >
1000+ < p style ="font-size:12px;color:#64748b;margin-top:4px " data-i18n ="api.statsHint "> </ p >
9891001 </ div >
9901002 </ div >
9911003 </ div >
@@ -1091,6 +1103,8 @@ <h1 class="logo"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stro
10911103 'settings.confirmReset' : '确定重置统计?' ,
10921104 'api.endpoints' : 'API 端点' ,
10931105 'api.modelList' : '模型列表' ,
1106+ 'api.stats' : '统计数据' ,
1107+ 'api.statsHint' : '需要在请求头中携带 API Key 鉴权(Authorization: Bearer sk-xxx),未启用 API Key 验证时无需鉴权' ,
10941108 'detail.title' : '账号详情' ,
10951109 'detail.basicInfo' : '基本信息' ,
10961110 'detail.email' : '邮箱' ,
@@ -1184,6 +1198,7 @@ <h1 class="logo"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stro
11841198 'common.add' : '添加' ,
11851199 'common.failed' : '失败' ,
11861200 'common.saveFailed' : '保存失败' ,
1201+ 'common.logout' : '退出登录' ,
11871202 'accounts.export' : '导出' ,
11881203 'export.title' : '导出账号' ,
11891204 'export.selectAll' : '全选' ,
@@ -1271,6 +1286,8 @@ <h1 class="logo"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stro
12711286 'settings.confirmReset' : 'Confirm reset statistics?' ,
12721287 'api.endpoints' : 'API Endpoints' ,
12731288 'api.modelList' : 'Model List' ,
1289+ 'api.stats' : 'Statistics' ,
1290+ 'api.statsHint' : 'Requires API Key in header (Authorization: Bearer sk-xxx). No auth needed if API Key verification is disabled.' ,
12741291 'detail.title' : 'Account Details' ,
12751292 'detail.basicInfo' : 'Basic Info' ,
12761293 'detail.email' : 'Email' ,
@@ -1360,6 +1377,7 @@ <h1 class="logo"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stro
13601377 'common.add' : 'Add' ,
13611378 'common.failed' : 'Failed' ,
13621379 'common.saveFailed' : 'Save failed' ,
1380+ 'common.logout' : 'Logout' ,
13631381 'accounts.export' : 'Export' ,
13641382 'export.title' : 'Export Accounts' ,
13651383 'export.selectAll' : 'Select All' ,
@@ -1489,6 +1507,14 @@ <h1 class="logo"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stro
14891507 document . querySelectorAll ( '.tab' ) . forEach ( tab => { tab . onclick = ( ) => switchTab ( tab . dataset . tab ) ; } ) ;
14901508 } ) ;
14911509 async function tryAutoLogin ( ) {
1510+ // 72h 过期检查
1511+ const loginTime = parseInt ( localStorage . getItem ( 'admin_login_time' ) || '0' ) ;
1512+ if ( loginTime && Date . now ( ) - loginTime > 72 * 3600 * 1000 ) {
1513+ localStorage . removeItem ( 'admin_password' ) ;
1514+ localStorage . removeItem ( 'admin_login_time' ) ;
1515+ password = '' ;
1516+ return ;
1517+ }
14921518 try {
14931519 const res = await fetch ( '/admin/api/status' , { headers : { 'X-Admin-Password' : password } } ) ;
14941520 if ( res . ok ) { showMain ( ) ; loadData ( ) ; }
@@ -1500,6 +1526,7 @@ <h1 class="logo"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stro
15001526 const res = await fetch ( '/admin/api/status' , { headers : { 'X-Admin-Password' : password } } ) ;
15011527 if ( res . ok ) {
15021528 localStorage . setItem ( 'admin_password' , password ) ;
1529+ localStorage . setItem ( 'admin_login_time' , Date . now ( ) . toString ( ) ) ;
15031530 showMain ( ) ; loadData ( ) ;
15041531 } else {
15051532 document . getElementById ( 'loginError' ) . textContent = t ( 'login.error' ) ;
@@ -1510,6 +1537,11 @@ <h1 class="logo"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stro
15101537 document . getElementById ( 'loginError' ) . classList . remove ( 'hidden' ) ;
15111538 }
15121539 }
1540+ function logout ( ) {
1541+ localStorage . removeItem ( 'admin_password' ) ;
1542+ localStorage . removeItem ( 'admin_login_time' ) ;
1543+ location . reload ( ) ;
1544+ }
15131545 function showMain ( ) {
15141546 document . getElementById ( 'loginPage' ) . classList . add ( 'hidden' ) ;
15151547 document . getElementById ( 'mainPage' ) . classList . remove ( 'hidden' ) ;
@@ -1519,6 +1551,7 @@ <h1 class="logo"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stro
15191551 document . getElementById ( 'claudeEndpoint' ) . textContent = baseUrl + '/v1/messages' ;
15201552 document . getElementById ( 'openaiEndpoint' ) . textContent = baseUrl + '/v1/chat/completions' ;
15211553 document . getElementById ( 'modelsEndpoint' ) . textContent = baseUrl + '/v1/models' ;
1554+ document . getElementById ( 'statsEndpoint' ) . textContent = baseUrl + '/v1/stats' ;
15221555 // 自动检查更新
15231556 setTimeout ( ( ) => checkUpdate ( false ) , 2000 ) ;
15241557 }
0 commit comments