mirror of
https://github.com/router-for-me/Cli-Proxy-API-Management-Center.git
synced 2026-02-02 19:00:49 +08:00
- Implemented the UI for importing Vertex AI credentials, including file selection and input fields for location and JSON key. - Enhanced internationalization support with appropriate labels and hints in both English and Chinese. - Removed the previous implementation of the Vertex AI credential import section to streamline the code.
981 lines
63 KiB
HTML
981 lines
63 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title data-i18n="title.login">CLI Proxy API Management Center</title>
|
||
<link rel="stylesheet" href="styles.css">
|
||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/codemirror.min.css">
|
||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/codemirror.min.js"></script>
|
||
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/mode/yaml/yaml.min.js"></script>
|
||
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/addon/edit/closebrackets.min.js"></script>
|
||
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/addon/comment/comment.min.js"></script>
|
||
<script src="https://cdn.jsdelivr.net/npm/js-yaml@4.1.0/dist/js-yaml.min.js"></script>
|
||
<script src="i18n.js"></script>
|
||
</head>
|
||
|
||
<body>
|
||
<!-- 自动登录加载页面 -->
|
||
<div id="auto-login-loading" class="login-container" style="display: none;">
|
||
<div class="login-card">
|
||
<div class="auto-login-content">
|
||
<div class="loading-spinner">
|
||
<div class="spinner"></div>
|
||
</div>
|
||
<h2 data-i18n="auto_login.title">正在自动登录...</h2>
|
||
<p data-i18n="auto_login.message">正在使用本地保存的连接信息尝试连接服务器</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 登录页面 -->
|
||
<div id="login-page" class="login-container">
|
||
<div class="login-card">
|
||
<div class="login-header">
|
||
<div class="login-header-top">
|
||
<h1 class="login-title">
|
||
<img id="login-logo" alt="Logo" style="display:none" />
|
||
<span data-i18n="title.login">CLI Proxy API Management Center</span>
|
||
</h1>
|
||
<div class="header-controls">
|
||
<div class="language-switcher">
|
||
<button id="language-toggle" class="btn btn-secondary language-btn">
|
||
<i class="fas fa-globe"></i>
|
||
<span data-i18n="language.switch">语言</span>
|
||
</button>
|
||
</div>
|
||
<div class="theme-switcher">
|
||
<button id="theme-toggle" class="btn btn-secondary theme-btn">
|
||
<i class="fas fa-moon"></i>
|
||
<span data-i18n="theme.switch">主题</span>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="login-body">
|
||
<div class="login-connection-info">
|
||
<div class="connection-summary">
|
||
<i class="fas fa-link"></i>
|
||
<div>
|
||
<h3 data-i18n="login.connection_title">连接地址</h3>
|
||
<p class="connection-url">
|
||
<span data-i18n="login.connection_current">当前地址</span>
|
||
<span class="connection-url-separator">:</span>
|
||
<span id="login-connection-url">-</span>
|
||
</p>
|
||
</div>
|
||
</div>
|
||
<p class="form-hint" data-i18n="login.connection_auto_hint">系统将自动使用当前访问地址进行连接</p>
|
||
</div>
|
||
|
||
<form class="login-form">
|
||
<div class="form-group">
|
||
<label for="login-api-base" data-i18n="login.custom_connection_label">自定义连接地址:</label>
|
||
<div class="input-group">
|
||
<input type="text" id="login-api-base" data-i18n-placeholder="login.custom_connection_placeholder">
|
||
<button type="button" id="login-reset-api-base"
|
||
class="btn btn-secondary connection-reset-btn">
|
||
<i class="fas fa-location-arrow"></i>
|
||
<span data-i18n="login.use_current_address">使用当前地址</span>
|
||
</button>
|
||
</div>
|
||
<p class="form-hint" data-i18n="login.custom_connection_hint">默认使用当前访问地址,若需要可手动输入其他地址。</p>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="login-management-key" data-i18n="login.management_key_label">管理密钥:</label>
|
||
<div class="input-group">
|
||
<input type="password" id="login-management-key" data-i18n-placeholder="login.management_key_placeholder" required>
|
||
<button type="button" class="btn btn-secondary toggle-key-visibility">
|
||
<i class="fas fa-eye"></i>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
|
||
<!-- 连接按钮 -->
|
||
<div class="form-actions">
|
||
<button type="button" id="login-submit" class="btn btn-primary login-btn">
|
||
<i class="fas fa-plug"></i> <span data-i18n="login.connect_button">Connect</span>
|
||
</button>
|
||
</div>
|
||
|
||
<div id="login-error" class="login-error" style="display: none;">
|
||
<i class="fas fa-exclamation-triangle"></i>
|
||
<span id="login-error-message"></span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 主页面 -->
|
||
<div id="main-page" style="display: none;">
|
||
<!-- 顶部导航栏 -->
|
||
<div class="top-navbar">
|
||
<div class="top-navbar-left">
|
||
<button class="mobile-menu-btn" id="mobile-menu-btn">
|
||
<i class="fas fa-bars"></i>
|
||
</button>
|
||
<button class="sidebar-toggle-btn-desktop" id="sidebar-toggle-btn-desktop" data-i18n-title="sidebar.toggle_collapse">
|
||
<i class="fas fa-bars"></i>
|
||
</button>
|
||
<div class="top-navbar-brand">
|
||
<img id="site-logo" class="top-navbar-brand-logo" alt="Logo" style="display:none" />
|
||
<span class="top-navbar-brand-text" data-i18n="title.main">CLI Proxy API Management Center</span>
|
||
</div>
|
||
</div>
|
||
<div class="top-navbar-actions">
|
||
<div class="header-controls">
|
||
<div class="language-switcher">
|
||
<button id="language-toggle-main" class="btn btn-secondary language-btn">
|
||
<i class="fas fa-globe"></i>
|
||
</button>
|
||
</div>
|
||
<div class="theme-switcher">
|
||
<button id="theme-toggle-main" class="btn btn-secondary theme-btn">
|
||
<i class="fas fa-moon"></i>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
<button id="connection-status" class="btn btn-secondary">
|
||
<i class="fas fa-circle"></i> <span data-i18n="header.check_connection">检查连接</span>
|
||
</button>
|
||
<button id="refresh-all" class="btn btn-primary">
|
||
<i class="fas fa-sync-alt"></i>
|
||
</button>
|
||
<button id="logout-btn" class="btn btn-danger">
|
||
<i class="fas fa-sign-out-alt"></i>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="layout" id="layout-container">
|
||
<!-- 侧边栏 -->
|
||
<nav class="sidebar" id="sidebar">
|
||
<!-- 导航菜单 -->
|
||
<ul class="nav-menu">
|
||
<li data-i18n-tooltip="nav.basic_settings"><a href="#basic-settings" class="nav-item active"
|
||
data-section="basic-settings">
|
||
<i class="fas fa-sliders-h"></i> <span data-i18n="nav.basic_settings">基础设置</span>
|
||
</a></li>
|
||
<li data-i18n-tooltip="nav.api_keys"><a href="#api-keys" class="nav-item" data-section="api-keys">
|
||
<i class="fas fa-key"></i> <span data-i18n="nav.api_keys">API 密钥</span>
|
||
</a></li>
|
||
<li data-i18n-tooltip="nav.ai_providers"><a href="#ai-providers" class="nav-item" data-section="ai-providers">
|
||
<i class="fas fa-robot"></i> <span data-i18n="nav.ai_providers">AI 提供商</span>
|
||
</a></li>
|
||
<li data-i18n-tooltip="nav.auth_files"><a href="#auth-files" class="nav-item" data-section="auth-files">
|
||
<i class="fas fa-file-alt"></i> <span data-i18n="nav.auth_files">认证文件</span>
|
||
</a></li>
|
||
<li data-i18n-tooltip="nav.usage_stats"><a href="#usage-stats" class="nav-item" data-section="usage-stats">
|
||
<i class="fas fa-chart-line"></i> <span data-i18n="nav.usage_stats">使用统计</span>
|
||
</a></li>
|
||
<li data-i18n-tooltip="nav.config_management"><a href="#config-management" class="nav-item" data-section="config-management">
|
||
<i class="fas fa-cog"></i> <span data-i18n="nav.config_management">配置管理</span>
|
||
</a></li>
|
||
<li id="logs-nav-item" data-i18n-tooltip="nav.logs" style="display: none;"><a href="#logs" class="nav-item" data-section="logs">
|
||
<i class="fas fa-scroll"></i> <span data-i18n="nav.logs">日志查看</span>
|
||
</a></li>
|
||
<li data-i18n-tooltip="nav.system_info"><a href="#system-info" class="nav-item" data-section="system-info">
|
||
<i class="fas fa-info-circle"></i> <span data-i18n="nav.system_info">系统信息</span>
|
||
</a></li>
|
||
</ul>
|
||
</nav>
|
||
|
||
<!-- 侧边栏遮罩(移动端) -->
|
||
<div class="sidebar-overlay" id="sidebar-overlay"></div>
|
||
|
||
<!-- 主内容包装器 -->
|
||
<div class="main-wrapper" id="main-wrapper">
|
||
<!-- 主内容区域 -->
|
||
<div class="main-content">
|
||
<!-- 内容区域 -->
|
||
<div class="content-area">
|
||
<!-- 基础设置 -->
|
||
<section id="basic-settings" class="content-section active">
|
||
<h2 data-i18n="basic_settings.title">基础设置</h2>
|
||
|
||
<!-- Debug 设置 -->
|
||
<div class="card">
|
||
<div class="card-header">
|
||
<h3><i class="fas fa-bug"></i> <span
|
||
data-i18n="basic_settings.debug_title">调试模式</span></h3>
|
||
</div>
|
||
<div class="card-content">
|
||
<div class="toggle-group">
|
||
<label class="toggle-switch">
|
||
<input type="checkbox" id="debug-toggle">
|
||
<span class="slider"></span>
|
||
</label>
|
||
<span class="toggle-label" data-i18n="basic_settings.debug_enable">启用调试模式</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 代理设置 -->
|
||
<div class="card">
|
||
<div class="card-header">
|
||
<h3><i class="fas fa-network-wired"></i> <span
|
||
data-i18n="basic_settings.proxy_title">代理设置</span></h3>
|
||
</div>
|
||
<div class="card-content">
|
||
<div class="form-group">
|
||
<label for="proxy-url" data-i18n="basic_settings.proxy_url_label">代理
|
||
URL:</label>
|
||
<div class="input-group">
|
||
<input type="text" id="proxy-url" data-i18n-placeholder="basic_settings.proxy_url_placeholder">
|
||
<button id="update-proxy" class="btn btn-primary"
|
||
data-i18n="basic_settings.proxy_update">更新</button>
|
||
<button id="clear-proxy" class="btn btn-danger"
|
||
data-i18n="basic_settings.proxy_clear">清空</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 请求重试设置 -->
|
||
<div class="card">
|
||
<div class="card-header">
|
||
<h3><i class="fas fa-redo"></i> <span
|
||
data-i18n="basic_settings.retry_title">请求重试</span></h3>
|
||
</div>
|
||
<div class="card-content">
|
||
<div class="form-group">
|
||
<label for="request-retry"
|
||
data-i18n="basic_settings.retry_count_label">重试次数:</label>
|
||
<div class="input-group">
|
||
<input type="number" id="request-retry" min="0" max="10" value="3">
|
||
<button id="update-retry" class="btn btn-primary"
|
||
data-i18n="basic_settings.retry_update">更新</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 配额超出行为 -->
|
||
<div class="card">
|
||
<div class="card-header">
|
||
<h3><i class="fas fa-exclamation-triangle"></i> <span
|
||
data-i18n="basic_settings.quota_title">配额超出行为</span></h3>
|
||
</div>
|
||
<div class="card-content">
|
||
<div class="toggle-group">
|
||
<label class="toggle-switch">
|
||
<input type="checkbox" id="switch-project-toggle">
|
||
<span class="slider"></span>
|
||
</label>
|
||
<span class="toggle-label"
|
||
data-i18n="basic_settings.quota_switch_project">自动切换项目</span>
|
||
</div>
|
||
<div class="toggle-group">
|
||
<label class="toggle-switch">
|
||
<input type="checkbox" id="switch-preview-model-toggle">
|
||
<span class="slider"></span>
|
||
</label>
|
||
<span class="toggle-label"
|
||
data-i18n="basic_settings.quota_switch_preview">切换到预览模型</span>
|
||
</div>
|
||
</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>
|
||
|
||
<!-- 日志记录设置 -->
|
||
<div class="card">
|
||
<div class="card-header">
|
||
<h3><i class="fas fa-file-alt"></i> <span
|
||
data-i18n="basic_settings.logging_title">日志记录</span></h3>
|
||
</div>
|
||
<div class="card-content">
|
||
<div class="toggle-group">
|
||
<label class="toggle-switch">
|
||
<input type="checkbox" id="logging-to-file-toggle">
|
||
<span class="slider"></span>
|
||
</label>
|
||
<span class="toggle-label"
|
||
data-i18n="basic_settings.logging_to_file_enable">启用日志记录到文件</span>
|
||
</div>
|
||
<div class="toggle-group">
|
||
<label class="toggle-switch">
|
||
<input type="checkbox" id="request-log-toggle">
|
||
<span class="slider"></span>
|
||
</label>
|
||
<span class="toggle-label"
|
||
data-i18n="basic_settings.request_log_enable">启用请求日志</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- WebSocket 鉴权 -->
|
||
<div class="card">
|
||
<div class="card-header">
|
||
<h3><i class="fas fa-shield-alt"></i> <span
|
||
data-i18n="basic_settings.ws_auth_title">WebSocket 鉴权</span></h3>
|
||
</div>
|
||
<div class="card-content">
|
||
<div class="toggle-group">
|
||
<label class="toggle-switch">
|
||
<input type="checkbox" id="ws-auth-toggle">
|
||
<span class="slider"></span>
|
||
</label>
|
||
<span class="toggle-label"
|
||
data-i18n="basic_settings.ws_auth_enable">启用 /ws/* 鉴权</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
</section>
|
||
|
||
<!-- API 密钥管理 -->
|
||
<section id="api-keys" class="content-section">
|
||
<h2 data-i18n="api_keys.title">API 密钥管理</h2>
|
||
|
||
<div class="card">
|
||
<div class="card-header">
|
||
<h3><i class="fas fa-key"></i> <span
|
||
data-i18n="api_keys.proxy_auth_title">代理服务认证密钥</span></h3>
|
||
<button id="add-api-key" class="btn btn-primary">
|
||
<i class="fas fa-plus"></i> <span data-i18n="api_keys.add_button">添加密钥</span>
|
||
</button>
|
||
</div>
|
||
<div class="card-content">
|
||
<div id="api-keys-list" class="key-list"></div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- AI 提供商 -->
|
||
<section id="ai-providers" class="content-section">
|
||
<h2 data-i18n="ai_providers.title">AI 提供商配置</h2>
|
||
|
||
<!-- Gemini API Keys -->
|
||
<div class="card">
|
||
<div class="card-header">
|
||
<h3><i class="fab fa-google"></i> <span data-i18n="ai_providers.gemini_title">Gemini
|
||
API 密钥</span></h3>
|
||
<button id="add-gemini-key" class="btn btn-primary">
|
||
<i class="fas fa-plus"></i> <span
|
||
data-i18n="ai_providers.gemini_add_button">添加密钥</span>
|
||
</button>
|
||
</div>
|
||
<div class="card-content">
|
||
<div id="gemini-keys-list" class="key-list"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Codex API Keys -->
|
||
<div class="card">
|
||
<div class="card-header">
|
||
<h3><i class="fas fa-code"></i> <span data-i18n="ai_providers.codex_title">Codex API
|
||
配置</span></h3>
|
||
<button id="add-codex-key" class="btn btn-primary">
|
||
<i class="fas fa-plus"></i> <span
|
||
data-i18n="ai_providers.codex_add_button">添加配置</span>
|
||
</button>
|
||
</div>
|
||
<div class="card-content">
|
||
<div id="codex-keys-list" class="provider-list"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Claude API Keys -->
|
||
<div class="card">
|
||
<div class="card-header">
|
||
<h3><i class="fas fa-brain"></i> <span data-i18n="ai_providers.claude_title">Claude
|
||
API 配置</span></h3>
|
||
<button id="add-claude-key" class="btn btn-primary">
|
||
<i class="fas fa-plus"></i> <span
|
||
data-i18n="ai_providers.claude_add_button">添加配置</span>
|
||
</button>
|
||
</div>
|
||
<div class="card-content">
|
||
<div id="claude-keys-list" class="provider-list"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- OpenAI 兼容提供商 -->
|
||
<div class="card">
|
||
<div class="card-header">
|
||
<h3><i class="fas fa-plug"></i> <span data-i18n="ai_providers.openai_title">OpenAI
|
||
兼容提供商</span></h3>
|
||
<button id="add-openai-provider" class="btn btn-primary">
|
||
<i class="fas fa-plus"></i> <span
|
||
data-i18n="ai_providers.openai_add_button">添加提供商</span>
|
||
</button>
|
||
</div>
|
||
<div class="card-content">
|
||
<div id="openai-providers-list" class="provider-list"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Vertex AI Credential Import -->
|
||
<div class="card" id="vertex-import-card">
|
||
<div class="card-header">
|
||
<h3><i class="fas fa-cloud-upload-alt"></i> <span data-i18n="vertex_import.title">Vertex AI 凭证导入</span></h3>
|
||
</div>
|
||
<div class="card-content">
|
||
<p class="form-hint" data-i18n="vertex_import.description">
|
||
上传 Google 服务账号 JSON 并保存为 vertex-<project>.json。
|
||
</p>
|
||
<div class="form-group">
|
||
<label for="vertex-location" data-i18n="vertex_import.location_label">区域 (可选)</label>
|
||
<input type="text" id="vertex-location" data-i18n-placeholder="vertex_import.location_placeholder" value="us-central1">
|
||
<p class="form-hint" data-i18n="vertex_import.location_hint">留空则使用默认 us-central1。</p>
|
||
</div>
|
||
<div class="form-group">
|
||
<label data-i18n="vertex_import.file_label">服务账号密钥 JSON</label>
|
||
<div class="input-group">
|
||
<input type="text" id="vertex-file-display" readonly data-i18n-placeholder="vertex_import.file_placeholder" placeholder="尚未选择文件">
|
||
<input type="file" id="vertex-file-input" accept=".json" style="display: none;">
|
||
<button type="button" id="vertex-select-file" class="btn btn-secondary">
|
||
<i class="fas fa-file-upload"></i> <span data-i18n="vertex_import.choose_file">选择文件</span>
|
||
</button>
|
||
</div>
|
||
<p class="form-hint" data-i18n="vertex_import.file_hint">仅支持 Google Cloud service account JSON。</p>
|
||
</div>
|
||
<div class="form-actions vertex-import-actions">
|
||
<button type="button" id="vertex-import-btn" class="btn btn-primary" disabled>
|
||
<i class="fas fa-cloud-upload-alt"></i> <span data-i18n="vertex_import.import_button">导入 Vertex 凭证</span>
|
||
</button>
|
||
</div>
|
||
<div id="vertex-import-result" class="vertex-import-result" style="display: none;">
|
||
<div class="vertex-import-result-header">
|
||
<i class="fas fa-check-circle"></i>
|
||
<span data-i18n="vertex_import.result_title">凭证已保存</span>
|
||
</div>
|
||
<ul>
|
||
<li><span data-i18n="vertex_import.result_project">项目 ID</span>: <code id="vertex-result-project">-</code></li>
|
||
<li><span data-i18n="vertex_import.result_email">服务账号</span>: <code id="vertex-result-email">-</code></li>
|
||
<li><span data-i18n="vertex_import.result_location">区域</span>: <code id="vertex-result-location">-</code></li>
|
||
<li><span data-i18n="vertex_import.result_file">存储文件</span>: <code id="vertex-result-file">-</code></li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 认证文件管理 -->
|
||
<section id="auth-files" class="content-section">
|
||
<h2 data-i18n="auth_files.title">认证文件管理</h2>
|
||
|
||
<div class="card" style="margin-bottom: 20px;">
|
||
<div class="card-content">
|
||
<p class="form-hint" data-i18n="auth_files.description">
|
||
这里管理 Qwen 和 Gemini 的认证配置文件。上传 JSON 格式的认证文件以启用相应的 AI 服务。
|
||
</p>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 认证文件 -->
|
||
<div class="card">
|
||
<div class="card-header card-header-with-filter">
|
||
<div class="header-left">
|
||
<h3><i class="fas fa-file-alt"></i> <span
|
||
data-i18n="auth_files.title_section">认证文件</span></h3>
|
||
<!-- 类型筛选 -->
|
||
<div class="auth-file-filter">
|
||
<button class="filter-btn active" data-type="all" data-i18n-text="auth_files.filter_all">All</button>
|
||
<button class="filter-btn" data-type="qwen" data-i18n-text="auth_files.filter_qwen">Qwen</button>
|
||
<button class="filter-btn" data-type="gemini" data-i18n-text="auth_files.filter_gemini">Gemini</button>
|
||
<button class="filter-btn" data-type="gemini-cli" data-i18n-text="auth_files.filter_gemini-cli">GeminiCLI</button>
|
||
<button class="filter-btn" data-type="aistudio" data-i18n-text="auth_files.filter_aistudio">AIStudio</button>
|
||
<button class="filter-btn" data-type="claude" data-i18n-text="auth_files.filter_claude">Claude</button>
|
||
<button class="filter-btn" data-type="codex" data-i18n-text="auth_files.filter_codex">Codex</button>
|
||
<button class="filter-btn" data-type="iflow" data-i18n-text="auth_files.filter_iflow">iFlow</button>
|
||
<button class="filter-btn" data-type="vertex" data-i18n-text="auth_files.filter_vertex">Vertex</button>
|
||
<button class="filter-btn" data-type="empty" data-i18n-text="auth_files.filter_empty">Empty</button>
|
||
</div>
|
||
</div>
|
||
<div class="header-actions">
|
||
<button id="upload-auth-file" class="btn btn-primary">
|
||
<i class="fas fa-upload"></i> <span
|
||
data-i18n="auth_files.upload_button">上传文件</span>
|
||
</button>
|
||
<button id="delete-all-auth-files" class="btn btn-danger">
|
||
<i class="fas fa-trash"></i> <span
|
||
data-i18n="auth_files.delete_all_button">删除全部</span>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
<div class="card-content">
|
||
<div id="auth-files-list" class="file-list file-grid"></div>
|
||
<input type="file" id="auth-file-input" accept=".json" style="display: none;">
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Codex OAuth -->
|
||
<div class="card" id="codex-oauth-card">
|
||
<div class="card-header">
|
||
<h3><i class="fas fa-code"></i> <span data-i18n="auth_login.codex_oauth_title">Codex
|
||
OAuth</span></h3>
|
||
<button id="codex-oauth-btn" class="btn btn-primary">
|
||
<i class="fas fa-sign-in-alt"></i> <span
|
||
data-i18n="auth_login.codex_oauth_button">开始 Codex 登录</span>
|
||
</button>
|
||
</div>
|
||
<div class="card-content">
|
||
<p class="form-hint" style="margin-bottom: 20px;"
|
||
data-i18n="auth_login.codex_oauth_hint">
|
||
通过 OAuth 流程登录 Codex 服务,自动获取并保存认证文件。
|
||
</p>
|
||
<div id="codex-oauth-content" style="display: none;">
|
||
<div class="form-group">
|
||
<label data-i18n="auth_login.codex_oauth_url_label">授权链接:</label>
|
||
<div class="input-group">
|
||
<input type="text" id="codex-oauth-url" readonly>
|
||
<button id="codex-open-link" class="btn btn-primary">
|
||
<i class="fas fa-external-link-alt"></i> <span
|
||
data-i18n="auth_login.codex_open_link">打开链接</span>
|
||
</button>
|
||
<button id="codex-copy-link" class="btn btn-secondary">
|
||
<i class="fas fa-copy"></i> <span
|
||
data-i18n="auth_login.codex_copy_link">复制链接</span>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
<div id="codex-oauth-status" class="form-hint" style="margin-top: 10px;"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Anthropic OAuth -->
|
||
<div class="card" id="anthropic-oauth-card">
|
||
<div class="card-header">
|
||
<h3><i class="fas fa-brain"></i> <span
|
||
data-i18n="auth_login.anthropic_oauth_title">Anthropic OAuth</span></h3>
|
||
<button id="anthropic-oauth-btn" class="btn btn-primary">
|
||
<i class="fas fa-sign-in-alt"></i> <span
|
||
data-i18n="auth_login.anthropic_oauth_button">开始 Anthropic 登录</span>
|
||
</button>
|
||
</div>
|
||
<div class="card-content">
|
||
<p class="form-hint" style="margin-bottom: 20px;"
|
||
data-i18n="auth_login.anthropic_oauth_hint">
|
||
通过 OAuth 流程登录 Anthropic (Claude) 服务,自动获取并保存认证文件。
|
||
</p>
|
||
<div id="anthropic-oauth-content" style="display: none;">
|
||
<div class="form-group">
|
||
<label data-i18n="auth_login.anthropic_oauth_url_label">授权链接:</label>
|
||
<div class="input-group">
|
||
<input type="text" id="anthropic-oauth-url" readonly>
|
||
<button id="anthropic-open-link" class="btn btn-primary">
|
||
<i class="fas fa-external-link-alt"></i> <span
|
||
data-i18n="auth_login.anthropic_open_link">打开链接</span>
|
||
</button>
|
||
<button id="anthropic-copy-link" class="btn btn-secondary">
|
||
<i class="fas fa-copy"></i> <span
|
||
data-i18n="auth_login.anthropic_copy_link">复制链接</span>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
<div id="anthropic-oauth-status" class="form-hint" style="margin-top: 10px;">
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Gemini CLI OAuth -->
|
||
<div class="card" id="gemini-cli-oauth-card">
|
||
<div class="card-header">
|
||
<h3><i class="fab fa-google"></i> <span
|
||
data-i18n="auth_login.gemini_cli_oauth_title">Gemini CLI OAuth</span></h3>
|
||
<button id="gemini-cli-oauth-btn" class="btn btn-primary">
|
||
<i class="fas fa-sign-in-alt"></i> <span
|
||
data-i18n="auth_login.gemini_cli_oauth_button">开始 Gemini CLI 登录</span>
|
||
</button>
|
||
</div>
|
||
<div class="card-content">
|
||
<p class="form-hint" style="margin-bottom: 20px;"
|
||
data-i18n="auth_login.gemini_cli_oauth_hint">
|
||
通过 OAuth 流程登录 Google Gemini CLI 服务,自动获取并保存认证文件。
|
||
</p>
|
||
<div class="form-group" style="margin-bottom: 20px;">
|
||
<label for="gemini-cli-project-id"
|
||
data-i18n="auth_login.gemini_cli_project_id_label">Google Cloud 项目 ID
|
||
(可选):</label>
|
||
<input type="text" id="gemini-cli-project-id"
|
||
data-i18n-placeholder="auth_login.gemini_cli_project_id_placeholder">
|
||
<div class="form-hint" data-i18n="auth_login.gemini_cli_project_id_hint">
|
||
如果指定了项目 ID,将使用该项目的认证信息。
|
||
</div>
|
||
</div>
|
||
<div id="gemini-cli-oauth-content" style="display: none;">
|
||
<div class="form-group">
|
||
<label data-i18n="auth_login.gemini_cli_oauth_url_label">授权链接:</label>
|
||
<div class="input-group">
|
||
<input type="text" id="gemini-cli-oauth-url" readonly>
|
||
<button id="gemini-cli-open-link" class="btn btn-primary">
|
||
<i class="fas fa-external-link-alt"></i> <span
|
||
data-i18n="auth_login.gemini_cli_open_link">打开链接</span>
|
||
</button>
|
||
<button id="gemini-cli-copy-link" class="btn btn-secondary">
|
||
<i class="fas fa-copy"></i> <span
|
||
data-i18n="auth_login.gemini_cli_copy_link">复制链接</span>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
<div id="gemini-cli-oauth-status" class="form-hint" style="margin-top: 10px;">
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Qwen OAuth -->
|
||
<div class="card" id="qwen-oauth-card">
|
||
<div class="card-header">
|
||
<h3><i class="fas fa-robot"></i> <span data-i18n="auth_login.qwen_oauth_title">Qwen
|
||
OAuth</span></h3>
|
||
<button id="qwen-oauth-btn" class="btn btn-primary">
|
||
<i class="fas fa-sign-in-alt"></i> <span
|
||
data-i18n="auth_login.qwen_oauth_button">开始 Qwen 登录</span>
|
||
</button>
|
||
</div>
|
||
<div class="card-content">
|
||
<p class="form-hint" style="margin-bottom: 20px;"
|
||
data-i18n="auth_login.qwen_oauth_hint">
|
||
通过设备授权流程登录 Qwen 服务,自动获取并保存认证文件。
|
||
</p>
|
||
<div id="qwen-oauth-content" style="display: none;">
|
||
<div class="form-group">
|
||
<label data-i18n="auth_login.qwen_oauth_url_label">授权链接:</label>
|
||
<div class="input-group">
|
||
<input type="text" id="qwen-oauth-url" readonly>
|
||
<button id="qwen-open-link" class="btn btn-primary">
|
||
<i class="fas fa-external-link-alt"></i> <span
|
||
data-i18n="auth_login.qwen_open_link">打开链接</span>
|
||
</button>
|
||
<button id="qwen-copy-link" class="btn btn-secondary">
|
||
<i class="fas fa-copy"></i> <span
|
||
data-i18n="auth_login.qwen_copy_link">复制链接</span>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
<div id="qwen-oauth-status" class="form-hint" style="margin-top: 10px;"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- iFlow OAuth -->
|
||
<div class="card" id="iflow-oauth-card">
|
||
<div class="card-header">
|
||
<h3><i class="fas fa-stream"></i> <span
|
||
data-i18n="auth_login.iflow_oauth_title">iFlow OAuth</span></h3>
|
||
<button id="iflow-oauth-btn" class="btn btn-primary">
|
||
<i class="fas fa-sign-in-alt"></i> <span
|
||
data-i18n="auth_login.iflow_oauth_button">开始 iFlow 登录</span>
|
||
</button>
|
||
</div>
|
||
<div class="card-content">
|
||
<p class="form-hint" style="margin-bottom: 20px;"
|
||
data-i18n="auth_login.iflow_oauth_hint">
|
||
通过 OAuth 流程登录 iFlow 服务,自动获取并保存认证文件。
|
||
</p>
|
||
<div id="iflow-oauth-content" style="display: none;">
|
||
<div class="form-group">
|
||
<label data-i18n="auth_login.iflow_oauth_url_label">授权链接:</label>
|
||
<div class="input-group">
|
||
<input type="text" id="iflow-oauth-url" readonly>
|
||
<button id="iflow-open-link" class="btn btn-primary">
|
||
<i class="fas fa-external-link-alt"></i> <span
|
||
data-i18n="auth_login.iflow_open_link">打开链接</span>
|
||
</button>
|
||
<button id="iflow-copy-link" class="btn btn-secondary">
|
||
<i class="fas fa-copy"></i> <span
|
||
data-i18n="auth_login.iflow_copy_link">复制链接</span>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
<div id="iflow-oauth-status" class="form-hint" style="margin-top: 10px;"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 日志查看 -->
|
||
<section id="logs" class="content-section">
|
||
<h2 data-i18n="logs.title">日志查看</h2>
|
||
|
||
<div class="card">
|
||
<div class="card-header">
|
||
<h3><i class="fas fa-scroll"></i> <span data-i18n="logs.log_content">日志内容</span></h3>
|
||
<div class="header-actions">
|
||
<div class="toggle-group" style="margin-right: 15px;">
|
||
<label class="toggle-switch" style="margin-right: 5px;">
|
||
<input type="checkbox" id="logs-auto-refresh-toggle">
|
||
<span class="slider"></span>
|
||
</label>
|
||
<span class="toggle-label" data-i18n="logs.auto_refresh" style="font-size: 0.9em;">自动刷新</span>
|
||
</div>
|
||
<button id="refresh-logs" class="btn btn-primary">
|
||
<i class="fas fa-sync-alt"></i> <span data-i18n="logs.refresh_button">刷新日志</span>
|
||
</button>
|
||
<button id="download-logs" class="btn btn-secondary">
|
||
<i class="fas fa-download"></i> <span data-i18n="logs.download_button">下载日志</span>
|
||
</button>
|
||
<button id="clear-logs" class="btn btn-danger">
|
||
<i class="fas fa-trash"></i> <span data-i18n="logs.clear_button">清空日志</span>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
<div class="card-content">
|
||
<div id="logs-content" class="logs-container">
|
||
<div class="loading-placeholder" data-i18n="logs.loading">正在加载日志...</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 使用统计 -->
|
||
<section id="usage-stats" class="content-section">
|
||
<h2 data-i18n="usage_stats.title">使用统计</h2>
|
||
|
||
<!-- 概览统计卡片 -->
|
||
<div class="stats-overview">
|
||
<div class="stat-card">
|
||
<div class="stat-icon">
|
||
<i class="fas fa-paper-plane"></i>
|
||
</div>
|
||
<div class="stat-content">
|
||
<div class="stat-number" id="total-requests">0</div>
|
||
<div class="stat-label" data-i18n="usage_stats.total_requests">总请求数</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="stat-card">
|
||
<div class="stat-icon success">
|
||
<i class="fas fa-check-circle"></i>
|
||
</div>
|
||
<div class="stat-content">
|
||
<div class="stat-number" id="success-requests">0</div>
|
||
<div class="stat-label" data-i18n="usage_stats.success_requests">成功请求</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="stat-card">
|
||
<div class="stat-icon error">
|
||
<i class="fas fa-exclamation-circle"></i>
|
||
</div>
|
||
<div class="stat-content">
|
||
<div class="stat-number" id="failed-requests">0</div>
|
||
<div class="stat-label" data-i18n="usage_stats.failed_requests">失败请求</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="stat-card">
|
||
<div class="stat-icon">
|
||
<i class="fas fa-coins"></i>
|
||
</div>
|
||
<div class="stat-content">
|
||
<div class="stat-number" id="total-tokens">0</div>
|
||
<div class="stat-label" data-i18n="usage_stats.total_tokens">总Token数</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 图表区域 -->
|
||
<div class="charts-container">
|
||
<!-- 请求趋势图 -->
|
||
<div class="card chart-card">
|
||
<div class="card-header">
|
||
<h3><i class="fas fa-chart-line"></i> <span
|
||
data-i18n="usage_stats.requests_trend">请求趋势</span></h3>
|
||
<div class="chart-controls">
|
||
<button class="btn btn-small" data-period="hour" id="requests-hour-btn">
|
||
<span data-i18n="usage_stats.by_hour">按小时</span>
|
||
</button>
|
||
<button class="btn btn-small active" data-period="day"
|
||
id="requests-day-btn">
|
||
<span data-i18n="usage_stats.by_day">按天</span>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
<div class="card-content">
|
||
<div class="chart-container">
|
||
<canvas id="requests-chart"></canvas>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Token使用趋势图 -->
|
||
<div class="card chart-card">
|
||
<div class="card-header">
|
||
<h3><i class="fas fa-chart-area"></i> <span
|
||
data-i18n="usage_stats.tokens_trend">Token 使用趋势</span></h3>
|
||
<div class="chart-controls">
|
||
<button class="btn btn-small" data-period="hour" id="tokens-hour-btn">
|
||
<span data-i18n="usage_stats.by_hour">按小时</span>
|
||
</button>
|
||
<button class="btn btn-small active" data-period="day" id="tokens-day-btn">
|
||
<span data-i18n="usage_stats.by_day">按天</span>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
<div class="card-content">
|
||
<div class="chart-container">
|
||
<canvas id="tokens-chart"></canvas>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- API详细统计 -->
|
||
<div class="card">
|
||
<div class="card-header">
|
||
<h3><i class="fas fa-list"></i> <span data-i18n="usage_stats.api_details">API
|
||
详细统计</span></h3>
|
||
<button id="refresh-usage-stats" class="btn btn-primary">
|
||
<i class="fas fa-sync-alt"></i> <span data-i18n="usage_stats.refresh">刷新</span>
|
||
</button>
|
||
</div>
|
||
<div class="card-content">
|
||
<div id="api-stats-table" class="api-stats-table">
|
||
<div class="loading-placeholder" data-i18n="common.loading">正在加载...</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 配置管理 -->
|
||
<section id="config-management" class="content-section">
|
||
<h2 data-i18n="config_management.title">配置管理</h2>
|
||
|
||
<div class="card">
|
||
<div class="card-header">
|
||
<h3><i class="fas fa-file-code"></i> <span data-i18n="config_management.editor_title">配置文件</span></h3>
|
||
<div class="editor-actions">
|
||
<button id="config-reload-btn" class="btn btn-secondary">
|
||
<i class="fas fa-sync-alt"></i> <span data-i18n="config_management.reload">重新加载</span>
|
||
</button>
|
||
<button id="config-save-btn" class="btn btn-primary">
|
||
<i class="fas fa-save"></i> <span data-i18n="config_management.save">保存</span>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
<div class="card-content">
|
||
<p class="form-hint" data-i18n="config_management.description">查看并编辑服务器上的 config.yaml 配置文件。保存前请确认语法正确。</p>
|
||
<div class="yaml-editor-container">
|
||
<textarea id="config-editor" class="yaml-editor" spellcheck="false" data-i18n="config_management.editor_placeholder"></textarea>
|
||
<div id="config-editor-status" class="editor-status" data-i18n="config_management.status_idle">等待操作</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 系统信息 -->
|
||
<section id="system-info" class="content-section">
|
||
<h2 data-i18n="system_info.title">系统信息</h2>
|
||
|
||
<!-- 连接信息卡片 -->
|
||
<div class="card">
|
||
<div class="card-header">
|
||
<h3><i class="fas fa-server"></i> <span data-i18n="connection.title">连接信息</span>
|
||
</h3>
|
||
</div>
|
||
<div class="card-content">
|
||
<div class="connection-info">
|
||
<div class="info-item">
|
||
<div class="info-label">
|
||
<i class="fas fa-globe"></i>
|
||
<span data-i18n="connection.server_address">服务器地址:</span>
|
||
</div>
|
||
<div class="info-value" id="display-api-url">-</div>
|
||
</div>
|
||
<div class="info-item">
|
||
<div class="info-label">
|
||
<i class="fas fa-circle"></i>
|
||
<span data-i18n="connection.status">连接状态:</span>
|
||
</div>
|
||
<div class="info-value" id="display-connection-status">
|
||
<span class="status-indicator disconnected"
|
||
data-i18n="common.disconnected">未连接</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="card">
|
||
<div class="card-header">
|
||
<h3><i class="fas fa-info-circle"></i> <span
|
||
data-i18n="system_info.connection_status_title">连接状态</span></h3>
|
||
</div>
|
||
<div class="card-content">
|
||
<div id="system-status" class="status-info">
|
||
<div class="status-item">
|
||
<span class="status-label" data-i18n="system_info.api_status_label">API
|
||
状态:</span>
|
||
<span id="api-status" class="status-value"
|
||
data-i18n="common.disconnected">未连接</span>
|
||
</div>
|
||
<div class="status-item">
|
||
<span class="status-label"
|
||
data-i18n="system_info.config_status_label">配置状态:</span>
|
||
<span id="config-status" class="status-value"
|
||
data-i18n="system_info.not_loaded">未加载</span>
|
||
</div>
|
||
<div class="status-item">
|
||
<span class="status-label"
|
||
data-i18n="system_info.last_update_label">最后更新:</span>
|
||
<span id="last-update" class="status-value">-</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
<!-- /内容区域 -->
|
||
|
||
<!-- 版本信息 -->
|
||
<footer class="version-footer">
|
||
<div class="version-info">
|
||
<span data-i18n="footer.version">版本</span>: __VERSION__
|
||
<span class="separator">•</span>
|
||
<span data-i18n="footer.author">作者</span>: CLI Proxy API Team
|
||
</div>
|
||
</footer>
|
||
</div>
|
||
<!-- /主内容区域 -->
|
||
</div>
|
||
<!-- /主内容包装器 -->
|
||
</div>
|
||
<!-- /主页面 -->
|
||
|
||
<!-- 模态框 -->
|
||
<div id="modal" class="modal">
|
||
<div class="modal-content">
|
||
<span class="close">×</span>
|
||
<div id="modal-body"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 通知 -->
|
||
<div id="notification" class="notification"></div>
|
||
|
||
</div>
|
||
|
||
<script src="app.js"></script>
|
||
</body>
|
||
|
||
</html>
|