mirror of
https://github.com/router-for-me/Cli-Proxy-API-Management-Center.git
synced 2026-02-03 03:10:50 +08:00
Compare commits
7 Commits
v0.1.2
...
v0.1.4-dev
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
86d60aad77 | ||
|
|
020fccc032 | ||
|
|
c162ab3a54 | ||
|
|
85d12e15d8 | ||
|
|
ebffb49f52 | ||
|
|
316c1ffc0d | ||
|
|
b3e54e7f14 |
@@ -10,7 +10,7 @@ Example URL:
|
||||
https://remote.router-for.me/
|
||||
|
||||
Minimum required version: ≥ 6.0.0
|
||||
Recommended version: ≥ 6.0.19
|
||||
Recommended version: ≥ 6.1.3
|
||||
|
||||
Since version 6.0.19, the WebUI has been rolled into the main program. You can access it by going to `/management.html` on the external port after firing up the main project.
|
||||
|
||||
@@ -43,7 +43,6 @@ Since version 6.0.19, the WebUI has been rolled into the main program. You can a
|
||||
- Download existing authentication files
|
||||
- Delete single or all authentication files
|
||||
- Display file details
|
||||
- **Gemini Web Token**: Direct authentication using browser cookies
|
||||
|
||||
### Usage Statistics
|
||||
- **Real-time Analytics**: Track API usage with interactive charts
|
||||
|
||||
@@ -8,7 +8,9 @@ https://github.com/router-for-me/CLIProxyAPI
|
||||
https://remote.router-for.me/
|
||||
|
||||
最低可用版本 ≥ 6.0.0
|
||||
推荐版本 ≥ 6.0.19
|
||||
|
||||
推荐版本 ≥ 6.1.3
|
||||
|
||||
自6.0.19起WebUI已经集成在主程序中 可以通过主项目开启的外部端口的`/management.html`访问
|
||||
|
||||
## 功能特点
|
||||
@@ -40,7 +42,6 @@ https://remote.router-for.me/
|
||||
- 下载现有认证文件
|
||||
- 删除单个或所有认证文件
|
||||
- 显示文件详细信息
|
||||
- **Gemini Web Token**: 使用浏览器 Cookie 直接认证
|
||||
|
||||
### 使用统计
|
||||
- **实时分析**: 通过交互式图表跟踪 API 使用情况
|
||||
|
||||
152
app.js
152
app.js
@@ -494,6 +494,7 @@ class CLIProxyManager {
|
||||
const updateRetry = document.getElementById('update-retry');
|
||||
const switchProjectToggle = document.getElementById('switch-project-toggle');
|
||||
const switchPreviewToggle = document.getElementById('switch-preview-model-toggle');
|
||||
const usageStatisticsToggle = document.getElementById('usage-statistics-enabled-toggle');
|
||||
|
||||
if (debugToggle) {
|
||||
debugToggle.addEventListener('change', (e) => this.updateDebug(e.target.checked));
|
||||
@@ -513,6 +514,9 @@ class CLIProxyManager {
|
||||
if (switchPreviewToggle) {
|
||||
switchPreviewToggle.addEventListener('change', (e) => this.updateSwitchPreviewModel(e.target.checked));
|
||||
}
|
||||
if (usageStatisticsToggle) {
|
||||
usageStatisticsToggle.addEventListener('change', (e) => this.updateUsageStatisticsEnabled(e.target.checked));
|
||||
}
|
||||
|
||||
// API 密钥管理
|
||||
const addApiKey = document.getElementById('add-api-key');
|
||||
@@ -538,12 +542,6 @@ class CLIProxyManager {
|
||||
}
|
||||
|
||||
|
||||
// Gemini Web Token
|
||||
const geminiWebTokenBtn = document.getElementById('gemini-web-token-btn');
|
||||
if (geminiWebTokenBtn) {
|
||||
geminiWebTokenBtn.addEventListener('click', () => this.showGeminiWebTokenModal());
|
||||
}
|
||||
|
||||
// 认证文件管理
|
||||
const uploadAuthFile = document.getElementById('upload-auth-file');
|
||||
const deleteAllAuthFiles = document.getElementById('delete-all-auth-files');
|
||||
@@ -1158,6 +1156,13 @@ class CLIProxyManager {
|
||||
}
|
||||
}
|
||||
|
||||
if (config['usage-statistics-enabled'] !== undefined) {
|
||||
const usageToggle = document.getElementById('usage-statistics-enabled-toggle');
|
||||
if (usageToggle) {
|
||||
usageToggle.checked = config['usage-statistics-enabled'];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// API 密钥
|
||||
if (config['api-keys']) {
|
||||
@@ -1192,6 +1197,7 @@ class CLIProxyManager {
|
||||
this.loadProxySettings(),
|
||||
this.loadRetrySettings(),
|
||||
this.loadQuotaSettings(),
|
||||
this.loadUsageStatisticsSettings(),
|
||||
this.loadApiKeys(),
|
||||
this.loadGeminiKeys(),
|
||||
this.loadCodexKeys(),
|
||||
@@ -1314,6 +1320,39 @@ class CLIProxyManager {
|
||||
}
|
||||
}
|
||||
|
||||
// 加载使用统计设置
|
||||
async loadUsageStatisticsSettings() {
|
||||
try {
|
||||
const config = await this.getConfig();
|
||||
if (config['usage-statistics-enabled'] !== undefined) {
|
||||
const usageToggle = document.getElementById('usage-statistics-enabled-toggle');
|
||||
if (usageToggle) {
|
||||
usageToggle.checked = config['usage-statistics-enabled'];
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载使用统计设置失败:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// 更新使用统计设置
|
||||
async updateUsageStatisticsEnabled(enabled) {
|
||||
try {
|
||||
await this.makeRequest('/usage-statistics-enabled', {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify({ value: enabled })
|
||||
});
|
||||
this.clearCache();
|
||||
this.showNotification(i18n.t('notification.usage_statistics_updated'), 'success');
|
||||
} catch (error) {
|
||||
this.showNotification(`${i18n.t('notification.update_failed')}: ${error.message}`, 'error');
|
||||
const usageToggle = document.getElementById('usage-statistics-enabled-toggle');
|
||||
if (usageToggle) {
|
||||
usageToggle.checked = !enabled;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 更新项目切换设置
|
||||
async updateSwitchProject(enabled) {
|
||||
try {
|
||||
@@ -2430,107 +2469,6 @@ class CLIProxyManager {
|
||||
|
||||
|
||||
|
||||
// 显示 Gemini Web Token 模态框
|
||||
showGeminiWebTokenModal() {
|
||||
const inlineSecure1psid = document.getElementById('secure-1psid-input');
|
||||
const inlineSecure1psidts = document.getElementById('secure-1psidts-input');
|
||||
const inlineLabel = document.getElementById('gemini-web-label-input');
|
||||
const modalBody = document.getElementById('modal-body');
|
||||
modalBody.innerHTML = `
|
||||
<h3>${i18n.t('auth_login.gemini_web_button')}</h3>
|
||||
<div class="gemini-web-form">
|
||||
<div class="form-group">
|
||||
<label for="modal-secure-1psid">${i18n.t('auth_login.secure_1psid_label')}</label>
|
||||
<input type="text" id="modal-secure-1psid" placeholder="${i18n.t('auth_login.secure_1psid_placeholder')}" required>
|
||||
<div class="form-hint">从浏览器开发者工具 → Application → Cookies 中获取</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="modal-secure-1psidts">${i18n.t('auth_login.secure_1psidts_label')}</label>
|
||||
<input type="text" id="modal-secure-1psidts" placeholder="${i18n.t('auth_login.secure_1psidts_placeholder')}" required>
|
||||
<div class="form-hint">从浏览器开发者工具 → Application → Cookies 中获取</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="modal-gemini-web-label">${i18n.t('auth_login.gemini_web_label_label')}</label>
|
||||
<input type="text" id="modal-gemini-web-label" placeholder="${i18n.t('auth_login.gemini_web_label_placeholder')}">
|
||||
<div class="form-hint">为此认证文件设置一个标签名称(可选)</div>
|
||||
</div>
|
||||
<div class="modal-actions">
|
||||
<button class="btn btn-secondary" onclick="manager.closeModal()">${i18n.t('common.cancel')}</button>
|
||||
<button class="btn btn-primary" onclick="manager.saveGeminiWebToken()">${i18n.t('common.save')}</button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
this.showModal();
|
||||
|
||||
const modalSecure1psid = document.getElementById('modal-secure-1psid');
|
||||
const modalSecure1psidts = document.getElementById('modal-secure-1psidts');
|
||||
const modalLabel = document.getElementById('modal-gemini-web-label');
|
||||
|
||||
if (modalSecure1psid && inlineSecure1psid) {
|
||||
modalSecure1psid.value = inlineSecure1psid.value.trim();
|
||||
}
|
||||
if (modalSecure1psidts && inlineSecure1psidts) {
|
||||
modalSecure1psidts.value = inlineSecure1psidts.value.trim();
|
||||
}
|
||||
if (modalLabel && inlineLabel) {
|
||||
modalLabel.value = inlineLabel.value.trim();
|
||||
}
|
||||
|
||||
if (modalSecure1psid) {
|
||||
modalSecure1psid.focus();
|
||||
}
|
||||
}
|
||||
|
||||
// 保存 Gemini Web Token
|
||||
async saveGeminiWebToken() {
|
||||
const secure1psid = document.getElementById('modal-secure-1psid').value.trim();
|
||||
const secure1psidts = document.getElementById('modal-secure-1psidts').value.trim();
|
||||
const label = document.getElementById('modal-gemini-web-label').value.trim();
|
||||
|
||||
if (!secure1psid || !secure1psidts) {
|
||||
this.showNotification('请填写完整的 Cookie 信息', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const requestBody = {
|
||||
secure_1psid: secure1psid,
|
||||
secure_1psidts: secure1psidts
|
||||
};
|
||||
|
||||
// 如果提供了 label,则添加到请求体中
|
||||
if (label) {
|
||||
requestBody.label = label;
|
||||
}
|
||||
|
||||
const response = await this.makeRequest('/gemini-web-token', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(requestBody)
|
||||
});
|
||||
|
||||
this.closeModal();
|
||||
this.loadAuthFiles(); // 刷新认证文件列表
|
||||
const inlineSecure1psid = document.getElementById('secure-1psid-input');
|
||||
const inlineSecure1psidts = document.getElementById('secure-1psidts-input');
|
||||
const inlineLabel = document.getElementById('gemini-web-label-input');
|
||||
if (inlineSecure1psid) {
|
||||
inlineSecure1psid.value = secure1psid;
|
||||
}
|
||||
if (inlineSecure1psidts) {
|
||||
inlineSecure1psidts.value = secure1psidts;
|
||||
}
|
||||
if (inlineLabel) {
|
||||
inlineLabel.value = label;
|
||||
}
|
||||
this.showNotification(`${i18n.t('auth_login.gemini_web_saved')}: ${response.file}`, 'success');
|
||||
} catch (error) {
|
||||
this.showNotification(`保存失败: ${error.message}`, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
// ===== Codex OAuth 相关方法 =====
|
||||
|
||||
// 开始 Codex OAuth 流程
|
||||
|
||||
61
index.html
61
index.html
@@ -275,6 +275,24 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 使用统计设置 -->
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3><i class="fas fa-chart-bar"></i> <span
|
||||
data-i18n="basic_settings.usage_statistics_title">使用统计</span></h3>
|
||||
</div>
|
||||
<div class="card-content">
|
||||
<div class="toggle-group">
|
||||
<label class="toggle-switch">
|
||||
<input type="checkbox" id="usage-statistics-enabled-toggle">
|
||||
<span class="slider"></span>
|
||||
</label>
|
||||
<span class="toggle-label"
|
||||
data-i18n="basic_settings.usage_statistics_enable">启用使用统计</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</section>
|
||||
|
||||
<!-- API 密钥管理 -->
|
||||
@@ -372,45 +390,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Gemini Web Token -->
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3><i class="fab fa-google"></i> <span
|
||||
data-i18n="auth_login.gemini_web_title">Gemini Web Token</span></h3>
|
||||
<button id="gemini-web-token-btn" class="btn btn-primary">
|
||||
<i class="fas fa-save"></i> <span data-i18n="auth_login.gemini_web_button">保存
|
||||
Gemini Web Token</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="card-content">
|
||||
<p class="form-hint" style="margin-bottom: 20px;"
|
||||
data-i18n="auth_login.gemini_web_hint">
|
||||
从浏览器开发者工具中获取 Gemini 网页版的 Cookie 值,用于直接认证访问 Gemini。
|
||||
</p>
|
||||
<div class="form-group">
|
||||
<label for="secure-1psid-input"
|
||||
data-i18n="auth_login.secure_1psid_label">__Secure-1PSID Cookie:</label>
|
||||
<input type="text" id="secure-1psid-input"
|
||||
data-i18n="auth_login.secure_1psid_placeholder"
|
||||
placeholder="输入 __Secure-1PSID cookie 值">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="secure-1psidts-input"
|
||||
data-i18n="auth_login.secure_1psidts_label">__Secure-1PSIDTS Cookie:</label>
|
||||
<input type="text" id="secure-1psidts-input"
|
||||
data-i18n="auth_login.secure_1psidts_placeholder"
|
||||
placeholder="输入 __Secure-1PSIDTS cookie 值">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="gemini-web-label-input"
|
||||
data-i18n="auth_login.gemini_web_label_label">Label (Optional):</label>
|
||||
<input type="text" id="gemini-web-label-input"
|
||||
data-i18n="auth_login.gemini_web_label_placeholder"
|
||||
placeholder="输入标签名称 (可选)">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 认证文件 -->
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
@@ -806,9 +785,9 @@
|
||||
<!-- 版本信息 -->
|
||||
<footer class="version-footer">
|
||||
<div class="version-info">
|
||||
<span data-i18n="footer.version">版本</span>: v0.1.0
|
||||
<span data-i18n="footer.version">版本</span>: v0.1.3
|
||||
<span class="separator">•</span>
|
||||
<span data-i18n="footer.author">作者</span>: Supra4E8C
|
||||
<span data-i18n="footer.author">作者</span>: CLI Proxy API Team
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
38
styles.css
38
styles.css
@@ -1923,44 +1923,6 @@ input:checked+.slider:before {
|
||||
}
|
||||
|
||||
|
||||
/* Gemini Web Token 模态框样式 */
|
||||
.gemini-web-form .form-group {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.gemini-web-form .form-group label {
|
||||
display: block;
|
||||
margin-bottom: 8px;
|
||||
color: var(--text-secondary);
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.gemini-web-form .form-group input {
|
||||
width: 100%;
|
||||
padding: 12px 16px;
|
||||
border: 2px solid var(--border-primary);
|
||||
border-radius: 8px;
|
||||
font-size: 14px;
|
||||
transition: all 0.3s ease;
|
||||
background: var(--bg-tertiary);
|
||||
color: var(--text-primary);
|
||||
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
|
||||
}
|
||||
|
||||
.gemini-web-form .form-group input:focus {
|
||||
outline: none;
|
||||
border-color: var(--border-focus);
|
||||
box-shadow: 0 0 0 3px var(--border-primary);
|
||||
}
|
||||
|
||||
.gemini-web-form .form-hint {
|
||||
margin-top: 6px;
|
||||
color: var(--text-tertiary);
|
||||
font-size: 12px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
/* 使用统计样式 */
|
||||
.stats-overview {
|
||||
display: grid;
|
||||
|
||||
Reference in New Issue
Block a user