mirror of
https://github.com/snailyp/gemini-balance.git
synced 2026-06-02 14:19:55 +08:00
本次提交主要包含以下内容:
1. **日志自动删除功能**:
* 新增环境变量 (`AUTO_DELETE_ERROR_LOGS_ENABLED`, `AUTO_DELETE_ERROR_LOGS_DAYS`, `AUTO_DELETE_REQUEST_LOGS_ENABLED`, `AUTO_DELETE_REQUEST_LOGS_DAYS`) 用于控制错误日志和请求日志的自动删除策略。
* 在 `app/config/config.py` 中添加了对这些新配置项的支持和验证逻辑 (Pydantic `validator` 更新为 `field_validator`)。
* 修改了 `app/log/logger.py` 以适应新的日志配置。
* 新增 `app/scheduler/scheduled_tasks.py` 用于执行定期的日志清理任务。
* 新增 `app/service/error_log/error_log_service.py` 和 `app/service/request_log/request_log_service.py` 来处理具体的日志删除逻辑。
* 更新了 `app/router/error_log_routes.py` 和 `app/router/scheduler_routes.py` 以集成新功能。
2. **前端配置页面更新**:
* 在 `app/templates/config_editor.html` 和 `app/static/js/config_editor.js` 中添加了用于配置日志自动删除选项的用户界面元素。
3. **代码和文件结构调整**:
* 删除了不再使用的 `app/scheduler/key_checker.py` 文件。
* 在 `.gitignore` 文件中添加了 `default_db` 以忽略该目录。
4. **其他**:
* 对 `app/core/application.py` 进行了相应调整。
该更新旨在增强应用的日志管理能力,提供更灵活的日志保留策略,并优化了配置界面的用户体验。
1293 lines
48 KiB
HTML
1293 lines
48 KiB
HTML
{% extends "base.html" %} {% block title %}配置编辑器 - Gemini Balance{%
|
||
endblock %} {% block head_extra_styles %}
|
||
<style>
|
||
/* config_editor.html specific styles */
|
||
/* Animations (already in base.html, but keep fade-in class usage) */
|
||
.fade-in {
|
||
animation: fadeIn 0.3s ease forwards;
|
||
}
|
||
/* Modal specific styles (already in base.html) */
|
||
.array-container {
|
||
max-height: 300px;
|
||
overflow-y: auto;
|
||
padding-right: 5px; /* Keep specific padding if needed */
|
||
}
|
||
#API_KEYS_container {
|
||
/* Keep specific ID styling if needed */
|
||
max-height: 300px;
|
||
overflow-y: auto;
|
||
}
|
||
.config-section {
|
||
display: none;
|
||
}
|
||
.config-section.active {
|
||
display: block;
|
||
animation: fadeIn 0.3s ease forwards; /* Use base animation */
|
||
}
|
||
.provider-config {
|
||
display: none;
|
||
}
|
||
.provider-config.active {
|
||
display: block;
|
||
}
|
||
/* Tailwind Toggle Switch Helper CSS */
|
||
.toggle-checkbox:checked {
|
||
@apply: right-0 border-primary-600;
|
||
right: 0;
|
||
border-color: #4f46e5;
|
||
}
|
||
.toggle-checkbox:checked + .toggle-label {
|
||
@apply: bg-primary-600;
|
||
background-color: #4f46e5;
|
||
}
|
||
/* 统一通知样式为黑色半透明,确保与 keys_status 一致 */
|
||
.notification {
|
||
background: rgba(0, 0, 0, 0.8) !important;
|
||
color: #fff !important;
|
||
}
|
||
</style>
|
||
{% endblock %} {% block content %}
|
||
<div class="container max-w-4xl mx-auto px-4">
|
||
<div class="glass-card rounded-2xl shadow-xl p-6 md:p-8">
|
||
<button
|
||
class="absolute top-6 right-6 bg-white bg-opacity-20 hover:bg-opacity-30 rounded-full w-8 h-8 flex items-center justify-center text-primary-600 transition-all duration-300"
|
||
onclick="refreshPage(this)"
|
||
>
|
||
<i class="fas fa-sync-alt"></i>
|
||
</button>
|
||
|
||
<h1
|
||
class="text-3xl font-extrabold text-center text-transparent bg-clip-text bg-gradient-to-r from-primary-600 to-primary-700 mb-4"
|
||
>
|
||
<img
|
||
src="/static/icons/logo.png"
|
||
alt="Gemini Balance Logo"
|
||
class="h-9 inline-block align-middle mr-2"
|
||
/>
|
||
Gemini Balance - 配置编辑
|
||
</h1>
|
||
|
||
<!-- Navigation Tabs -->
|
||
<div class="flex justify-center mb-8 overflow-x-auto pb-2 gap-2">
|
||
<a
|
||
href="/config"
|
||
class="whitespace-nowrap flex items-center justify-center gap-2 px-6 py-3 font-medium rounded-lg bg-primary-600 text-white shadow-md"
|
||
>
|
||
<i class="fas fa-cog"></i> 配置编辑
|
||
</a>
|
||
<a
|
||
href="/keys"
|
||
class="whitespace-nowrap flex items-center justify-center gap-2 px-6 py-3 font-medium rounded-lg bg-white bg-opacity-50 hover:bg-opacity-70 text-gray-700 transition-all duration-200"
|
||
>
|
||
<i class="fas fa-tachometer-alt"></i> 监控面板
|
||
</a>
|
||
<a
|
||
href="/logs"
|
||
class="whitespace-nowrap flex items-center justify-center gap-2 px-6 py-3 font-medium rounded-lg bg-white bg-opacity-50 hover:bg-opacity-70 text-gray-700 transition-all duration-200"
|
||
>
|
||
<i class="fas fa-exclamation-triangle"></i> 错误日志
|
||
</a>
|
||
</div>
|
||
|
||
<!-- Config Tabs -->
|
||
<div class="flex justify-center mb-6 flex-wrap gap-2">
|
||
<button
|
||
class="tab-btn bg-primary-600 text-white px-5 py-2 rounded-full shadow-md font-medium text-sm"
|
||
data-tab="api"
|
||
>
|
||
API配置
|
||
</button>
|
||
<button
|
||
class="tab-btn bg-white bg-opacity-50 text-gray-700 px-5 py-2 rounded-full font-medium text-sm hover:bg-opacity-70 transition-all duration-200"
|
||
data-tab="model"
|
||
>
|
||
模型配置
|
||
</button>
|
||
<button
|
||
class="tab-btn bg-white bg-opacity-50 text-gray-700 px-5 py-2 rounded-full font-medium text-sm hover:bg-opacity-70 transition-all duration-200"
|
||
data-tab="image"
|
||
>
|
||
图像生成
|
||
</button>
|
||
<button
|
||
class="tab-btn bg-white bg-opacity-50 text-gray-700 px-5 py-2 rounded-full font-medium text-sm hover:bg-opacity-70 transition-all duration-200"
|
||
data-tab="stream"
|
||
>
|
||
流式输出
|
||
</button>
|
||
<button
|
||
class="tab-btn bg-white bg-opacity-50 text-gray-700 px-5 py-2 rounded-full font-medium text-sm hover:bg-opacity-70 transition-all duration-200"
|
||
data-tab="scheduler"
|
||
>
|
||
定时任务
|
||
</button>
|
||
<button
|
||
class="tab-btn bg-white bg-opacity-50 text-gray-700 px-5 py-2 rounded-full font-medium text-sm hover:bg-opacity-70 transition-all duration-200"
|
||
data-tab="logging"
|
||
>
|
||
日志配置
|
||
</button>
|
||
</div>
|
||
|
||
<!-- Save Status Banner (Removed - using notification component now) -->
|
||
|
||
<!-- Configuration Form -->
|
||
<form id="configForm" class="mt-6">
|
||
<!-- API 相关配置 -->
|
||
<div
|
||
class="config-section active bg-white bg-opacity-70 rounded-xl p-6 mb-6 shadow-lg"
|
||
id="api-section"
|
||
>
|
||
<h2
|
||
class="text-xl font-bold mb-6 pb-3 border-b border-gray-200 flex items-center gap-2"
|
||
>
|
||
<i class="fas fa-key text-primary-600"></i> API相关配置
|
||
</h2>
|
||
|
||
<!-- API密钥列表 -->
|
||
<div class="mb-6">
|
||
<label for="API_KEYS" class="block font-semibold mb-2 text-gray-700"
|
||
>API密钥列表</label
|
||
>
|
||
<div class="mb-2">
|
||
<input
|
||
type="search"
|
||
id="apiKeySearchInput"
|
||
placeholder="搜索密钥..."
|
||
class="w-full px-4 py-2 rounded-lg border border-gray-300 focus:border-primary-500 focus:ring focus:ring-primary-200 focus:ring-opacity-50"
|
||
/>
|
||
</div>
|
||
<div
|
||
class="array-container bg-white rounded-lg border border-gray-200 p-4 mb-2"
|
||
id="API_KEYS_container"
|
||
>
|
||
<!-- 数组项将在这里动态添加 -->
|
||
</div>
|
||
<div class="flex justify-end gap-2">
|
||
<button
|
||
type="button"
|
||
class="bg-danger-600 hover:bg-danger-700 text-white px-4 py-2 rounded-lg font-medium transition-all duration-200 flex items-center gap-2"
|
||
id="bulkDeleteApiKeyBtn"
|
||
>
|
||
<i class="fas fa-trash-alt"></i> 删除密钥
|
||
</button>
|
||
<button
|
||
type="button"
|
||
class="bg-primary-600 hover:bg-primary-700 text-white px-4 py-2 rounded-lg font-medium transition-all duration-200 flex items-center gap-2"
|
||
id="addApiKeyBtn"
|
||
>
|
||
<i class="fas fa-plus"></i> 添加密钥
|
||
</button>
|
||
</div>
|
||
<small class="text-gray-500 mt-1 block"
|
||
>Gemini API密钥列表,每行一个</small
|
||
>
|
||
</div>
|
||
|
||
<!-- 允许的令牌列表 -->
|
||
<div class="mb-6">
|
||
<label
|
||
for="ALLOWED_TOKENS"
|
||
class="block font-semibold mb-2 text-gray-700"
|
||
>允许的令牌列表</label
|
||
>
|
||
<div
|
||
class="array-container bg-white rounded-lg border border-gray-200 p-4 mb-2"
|
||
id="ALLOWED_TOKENS_container"
|
||
>
|
||
<!-- 数组项将在这里动态添加 -->
|
||
</div>
|
||
<div class="flex justify-end">
|
||
<button
|
||
type="button"
|
||
class="bg-primary-600 hover:bg-primary-700 text-white px-4 py-2 rounded-lg font-medium transition-all duration-200 flex items-center gap-2"
|
||
onclick="addArrayItem('ALLOWED_TOKENS')"
|
||
>
|
||
<i class="fas fa-plus"></i> 添加令牌
|
||
</button>
|
||
</div>
|
||
<small class="text-gray-500 mt-1 block">允许访问API的令牌列表</small>
|
||
</div>
|
||
|
||
<!-- 认证令牌 -->
|
||
<div class="mb-6">
|
||
<label for="AUTH_TOKEN" class="block font-semibold mb-2 text-gray-700"
|
||
>认证令牌</label
|
||
>
|
||
<div class="flex items-center">
|
||
<div
|
||
class="flex items-center flex-grow border border-gray-300 rounded-md focus-within:border-primary-500 focus-within:ring focus-within:ring-primary-200 focus-within:ring-opacity-50"
|
||
>
|
||
<input
|
||
type="text"
|
||
id="AUTH_TOKEN"
|
||
name="AUTH_TOKEN"
|
||
placeholder="默认使用ALLOWED_TOKENS中的第一个"
|
||
class="array-input flex-grow px-3 py-2 border-none rounded-l-md focus:outline-none sensitive-input"
|
||
/>
|
||
<button
|
||
type="button"
|
||
id="generateAuthTokenBtn"
|
||
class="generate-btn px-2 py-2 text-gray-500 hover:text-primary-600 focus:outline-none rounded-r-md bg-gray-100 hover:bg-gray-200 transition-colors"
|
||
title="生成随机令牌"
|
||
>
|
||
<i class="fas fa-dice"></i>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
<small class="text-gray-500 mt-1 block">用于API认证的令牌</small>
|
||
</div>
|
||
|
||
<!-- API基础URL -->
|
||
<div class="mb-6">
|
||
<label for="BASE_URL" class="block font-semibold mb-2 text-gray-700"
|
||
>API基础URL</label
|
||
>
|
||
<input
|
||
type="text"
|
||
id="BASE_URL"
|
||
name="BASE_URL"
|
||
placeholder="https://generativelanguage.googleapis.com/v1beta"
|
||
class="w-full px-4 py-3 rounded-lg border border-gray-300 focus:border-primary-500 focus:ring focus:ring-primary-200 focus:ring-opacity-50"
|
||
/>
|
||
<small class="text-gray-500 mt-1 block">Gemini API的基础URL</small>
|
||
</div>
|
||
|
||
<!-- 最大失败次数 -->
|
||
<div class="mb-6">
|
||
<label
|
||
for="MAX_FAILURES"
|
||
class="block font-semibold mb-2 text-gray-700"
|
||
>最大失败次数</label
|
||
>
|
||
<input
|
||
type="number"
|
||
id="MAX_FAILURES"
|
||
name="MAX_FAILURES"
|
||
min="1"
|
||
max="100"
|
||
class="w-full px-4 py-3 rounded-lg border border-gray-300 focus:border-primary-500 focus:ring focus:ring-primary-200 focus:ring-opacity-50"
|
||
/>
|
||
<small class="text-gray-500 mt-1 block"
|
||
>API密钥失败后标记为无效的次数</small
|
||
>
|
||
</div>
|
||
|
||
<!-- 请求超时时间 -->
|
||
<div class="mb-6">
|
||
<label for="TIME_OUT" class="block font-semibold mb-2 text-gray-700"
|
||
>请求超时时间(秒)</label
|
||
>
|
||
<input
|
||
type="number"
|
||
id="TIME_OUT"
|
||
name="TIME_OUT"
|
||
min="1"
|
||
max="600"
|
||
class="w-full px-4 py-3 rounded-lg border border-gray-300 focus:border-primary-500 focus:ring focus:ring-primary-200 focus:ring-opacity-50"
|
||
/>
|
||
<small class="text-gray-500 mt-1 block">API请求的超时时间</small>
|
||
</div>
|
||
|
||
<!-- 最大重试次数 -->
|
||
<div class="mb-6">
|
||
<label
|
||
for="MAX_RETRIES"
|
||
class="block font-semibold mb-2 text-gray-700"
|
||
>最大重试次数</label
|
||
>
|
||
<input
|
||
type="number"
|
||
id="MAX_RETRIES"
|
||
name="MAX_RETRIES"
|
||
min="0"
|
||
max="10"
|
||
class="w-full px-4 py-3 rounded-lg border border-gray-300 focus:border-primary-500 focus:ring focus:ring-primary-200 focus:ring-opacity-50"
|
||
/>
|
||
<small class="text-gray-500 mt-1 block"
|
||
>API请求失败后的最大重试次数</small
|
||
>
|
||
</div>
|
||
<!-- 代理服务器列表 -->
|
||
<div class="mb-6">
|
||
<label for="PROXIES" class="block font-semibold mb-2 text-gray-700"
|
||
>代理服务器列表</label
|
||
>
|
||
<div
|
||
class="array-container bg-white rounded-lg border border-gray-200 p-4 mb-2"
|
||
id="PROXIES_container"
|
||
>
|
||
<!-- 代理项将在这里动态添加 -->
|
||
</div>
|
||
<div class="flex justify-end gap-2">
|
||
<button
|
||
type="button"
|
||
class="bg-danger-600 hover:bg-danger-700 text-white px-4 py-2 rounded-lg font-medium transition-all duration-200 flex items-center gap-2"
|
||
id="bulkDeleteProxyBtn"
|
||
>
|
||
<i class="fas fa-trash-alt"></i> 删除代理
|
||
</button>
|
||
<button
|
||
type="button"
|
||
class="bg-primary-600 hover:bg-primary-700 text-white px-4 py-2 rounded-lg font-medium transition-all duration-200 flex items-center gap-2"
|
||
id="addProxyBtn"
|
||
>
|
||
<i class="fas fa-plus"></i> 添加代理
|
||
</button>
|
||
</div>
|
||
<small class="text-gray-500 mt-1 block"
|
||
>代理服务器列表,支持 http 和 socks5 格式,例如:
|
||
http://user:pass@host:port 或
|
||
socks5://host:port。点击按钮可批量添加或删除。</small
|
||
>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 模型相关配置 -->
|
||
<div
|
||
class="config-section bg-white bg-opacity-70 rounded-xl p-6 mb-6 shadow-lg"
|
||
id="model-section"
|
||
>
|
||
<h2
|
||
class="text-xl font-bold mb-6 pb-3 border-b border-gray-200 flex items-center gap-2"
|
||
>
|
||
<i class="fas fa-robot text-primary-600"></i> 模型相关配置
|
||
</h2>
|
||
|
||
<!-- 测试模型 -->
|
||
<div class="mb-6">
|
||
<label for="TEST_MODEL" class="block font-semibold mb-2 text-gray-700"
|
||
>测试模型</label
|
||
>
|
||
<input
|
||
type="text"
|
||
id="TEST_MODEL"
|
||
name="TEST_MODEL"
|
||
placeholder="gemini-1.5-flash"
|
||
class="w-full px-4 py-3 rounded-lg border border-gray-300 focus:border-primary-500 focus:ring focus:ring-primary-200 focus:ring-opacity-50"
|
||
/>
|
||
<small class="text-gray-500 mt-1 block">用于测试API密钥的模型</small>
|
||
</div>
|
||
|
||
<!-- 图像模型列表 -->
|
||
<div class="mb-6">
|
||
<label
|
||
for="IMAGE_MODELS"
|
||
class="block font-semibold mb-2 text-gray-700"
|
||
>图像模型列表</label
|
||
>
|
||
<div
|
||
class="array-container bg-white rounded-lg border border-gray-200 p-4 mb-2"
|
||
id="IMAGE_MODELS_container"
|
||
>
|
||
<!-- 数组项将在这里动态添加 -->
|
||
</div>
|
||
<div class="flex justify-end">
|
||
<button
|
||
type="button"
|
||
class="bg-primary-600 hover:bg-primary-700 text-white px-4 py-2 rounded-lg font-medium transition-all duration-200 flex items-center gap-2"
|
||
onclick="addArrayItem('IMAGE_MODELS')"
|
||
>
|
||
<i class="fas fa-plus"></i> 添加模型
|
||
</button>
|
||
</div>
|
||
<small class="text-gray-500 mt-1 block">支持图像处理的模型列表</small>
|
||
</div>
|
||
|
||
<!-- 搜索模型列表 -->
|
||
<div class="mb-6">
|
||
<label
|
||
for="SEARCH_MODELS"
|
||
class="block font-semibold mb-2 text-gray-700"
|
||
>搜索模型列表</label
|
||
>
|
||
<div
|
||
class="array-container bg-white rounded-lg border border-gray-200 p-4 mb-2"
|
||
id="SEARCH_MODELS_container"
|
||
>
|
||
<!-- 数组项将在这里动态添加 -->
|
||
</div>
|
||
<div class="flex justify-end">
|
||
<button
|
||
type="button"
|
||
class="bg-primary-600 hover:bg-primary-700 text-white px-4 py-2 rounded-lg font-medium transition-all duration-200 flex items-center gap-2"
|
||
onclick="addArrayItem('SEARCH_MODELS')"
|
||
>
|
||
<i class="fas fa-plus"></i> 添加模型
|
||
</button>
|
||
</div>
|
||
<small class="text-gray-500 mt-1 block">支持搜索功能的模型列表</small>
|
||
</div>
|
||
|
||
<!-- 过滤模型列表 -->
|
||
<div class="mb-6">
|
||
<label
|
||
for="FILTERED_MODELS"
|
||
class="block font-semibold mb-2 text-gray-700"
|
||
>过滤模型列表</label
|
||
>
|
||
<div
|
||
class="array-container bg-white rounded-lg border border-gray-200 p-4 mb-2"
|
||
id="FILTERED_MODELS_container"
|
||
>
|
||
<!-- 数组项将在这里动态添加 -->
|
||
</div>
|
||
<div class="flex justify-end">
|
||
<button
|
||
type="button"
|
||
class="bg-primary-600 hover:bg-primary-700 text-white px-4 py-2 rounded-lg font-medium transition-all duration-200 flex items-center gap-2"
|
||
onclick="addArrayItem('FILTERED_MODELS')"
|
||
>
|
||
<i class="fas fa-plus"></i> 添加模型
|
||
</button>
|
||
</div>
|
||
<small class="text-gray-500 mt-1 block">需要过滤的模型列表</small>
|
||
</div>
|
||
|
||
<!-- 启用代码执行工具 -->
|
||
<div class="mb-6 flex items-center justify-between">
|
||
<label
|
||
for="TOOLS_CODE_EXECUTION_ENABLED"
|
||
class="font-semibold text-gray-700"
|
||
>启用代码执行工具</label
|
||
>
|
||
<div
|
||
class="relative inline-block w-10 mr-2 align-middle select-none transition duration-200 ease-in"
|
||
>
|
||
<input
|
||
type="checkbox"
|
||
name="TOOLS_CODE_EXECUTION_ENABLED"
|
||
id="TOOLS_CODE_EXECUTION_ENABLED"
|
||
class="toggle-checkbox absolute block w-6 h-6 rounded-full bg-white border-4 appearance-none cursor-pointer"
|
||
/>
|
||
<label
|
||
for="TOOLS_CODE_EXECUTION_ENABLED"
|
||
class="toggle-label block overflow-hidden h-6 rounded-full bg-gray-300 cursor-pointer"
|
||
></label>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 显示搜索链接 -->
|
||
<div class="mb-6 flex items-center justify-between">
|
||
<label for="SHOW_SEARCH_LINK" class="font-semibold text-gray-700"
|
||
>显示搜索链接</label
|
||
>
|
||
<div
|
||
class="relative inline-block w-10 mr-2 align-middle select-none transition duration-200 ease-in"
|
||
>
|
||
<input
|
||
type="checkbox"
|
||
name="SHOW_SEARCH_LINK"
|
||
id="SHOW_SEARCH_LINK"
|
||
class="toggle-checkbox absolute block w-6 h-6 rounded-full bg-white border-4 appearance-none cursor-pointer"
|
||
/>
|
||
<label
|
||
for="SHOW_SEARCH_LINK"
|
||
class="toggle-label block overflow-hidden h-6 rounded-full bg-gray-300 cursor-pointer"
|
||
></label>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 显示思考过程 -->
|
||
<div class="mb-6 flex items-center justify-between">
|
||
<label for="SHOW_THINKING_PROCESS" class="font-semibold text-gray-700"
|
||
>显示思考过程</label
|
||
>
|
||
<div
|
||
class="relative inline-block w-10 mr-2 align-middle select-none transition duration-200 ease-in"
|
||
>
|
||
<input
|
||
type="checkbox"
|
||
name="SHOW_THINKING_PROCESS"
|
||
id="SHOW_THINKING_PROCESS"
|
||
class="toggle-checkbox absolute block w-6 h-6 rounded-full bg-white border-4 appearance-none cursor-pointer"
|
||
/>
|
||
<label
|
||
for="SHOW_THINKING_PROCESS"
|
||
class="toggle-label block overflow-hidden h-6 rounded-full bg-gray-300 cursor-pointer"
|
||
></label>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 思考模型列表 -->
|
||
<div class="mb-6">
|
||
<label
|
||
for="THINKING_MODELS"
|
||
class="block font-semibold mb-2 text-gray-700"
|
||
>思考模型列表</label
|
||
>
|
||
<div
|
||
class="array-container bg-white rounded-lg border border-gray-200 p-4 mb-2"
|
||
id="THINKING_MODELS_container"
|
||
>
|
||
<!-- 数组项将在这里动态添加 -->
|
||
</div>
|
||
<div class="flex justify-end">
|
||
<button
|
||
type="button"
|
||
class="bg-primary-600 hover:bg-primary-700 text-white px-4 py-2 rounded-lg font-medium transition-all duration-200 flex items-center gap-2"
|
||
onclick="addArrayItem('THINKING_MODELS')"
|
||
>
|
||
<i class="fas fa-plus"></i> 添加模型
|
||
</button>
|
||
</div>
|
||
<small class="text-gray-500 mt-1 block"
|
||
>用于"思考过程"的模型列表</small
|
||
>
|
||
</div>
|
||
|
||
<!-- 思考模型预算映射 -->
|
||
<div class="mb-6">
|
||
<label
|
||
for="THINKING_BUDGET_MAP"
|
||
class="block font-semibold mb-2 text-gray-700"
|
||
>思考模型预算映射</label
|
||
>
|
||
<div
|
||
class="bg-white rounded-lg border border-gray-200 p-4 mb-2 space-y-3"
|
||
id="THINKING_BUDGET_MAP_container"
|
||
>
|
||
<!-- 键值对将在这里动态添加 -->
|
||
<div class="text-gray-500 text-sm italic">
|
||
请先在上方添加思考模型,然后在此处配置预算。
|
||
</div>
|
||
</div>
|
||
<!-- 移除添加预算映射按钮 -->
|
||
<!-- <div class="flex justify-end">
|
||
<button type="button" class="bg-primary-600 hover:bg-primary-700 text-white px-4 py-2 rounded-lg font-medium transition-all duration-200 flex items-center gap-2" id="addBudgetMapItemBtn">
|
||
<i class="fas fa-plus"></i> 添加预算映射
|
||
</button>
|
||
</div> -->
|
||
<small class="text-gray-500 mt-1 block"
|
||
>为每个思考模型设置预算(整数,最大值
|
||
24576),此项与上方模型列表自动关联。</small
|
||
>
|
||
</div>
|
||
<!-- 安全设置 -->
|
||
<div class="mb-6">
|
||
<label
|
||
for="SAFETY_SETTINGS"
|
||
class="block font-semibold mb-2 text-gray-700"
|
||
>安全设置 (Safety Settings)</label
|
||
>
|
||
<div
|
||
class="bg-white rounded-lg border border-gray-200 p-4 mb-2 space-y-3"
|
||
id="SAFETY_SETTINGS_container"
|
||
>
|
||
<!-- 安全设置项将在这里动态添加 -->
|
||
<div class="text-gray-500 text-sm italic">
|
||
定义模型的安全过滤阈值。
|
||
</div>
|
||
</div>
|
||
<div class="flex justify-end">
|
||
<button
|
||
type="button"
|
||
class="bg-primary-600 hover:bg-primary-700 text-white px-4 py-2 rounded-lg font-medium transition-all duration-200 flex items-center gap-2"
|
||
id="addSafetySettingBtn"
|
||
>
|
||
<i class="fas fa-plus"></i> 添加安全设置
|
||
</button>
|
||
</div>
|
||
<small class="text-gray-500 mt-1 block"
|
||
>配置模型的安全过滤级别,例如 HARM_CATEGORY_HARASSMENT:
|
||
BLOCK_NONE。</small
|
||
>
|
||
<small class="text-red-500 mt-1 block"
|
||
>建议设置成OFF,其他值会影响输出速度,非必要不要随便改动。</small
|
||
>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 图像生成相关配置 -->
|
||
<div
|
||
class="config-section bg-white bg-opacity-70 rounded-xl p-6 mb-6 shadow-lg"
|
||
id="image-section"
|
||
>
|
||
<h2
|
||
class="text-xl font-bold mb-6 pb-3 border-b border-gray-200 flex items-center gap-2"
|
||
>
|
||
<i class="fas fa-image text-primary-600"></i> 图像生成配置
|
||
</h2>
|
||
|
||
<!-- 付费API密钥 -->
|
||
<div class="mb-6">
|
||
<label for="PAID_KEY" class="block font-semibold mb-2 text-gray-700"
|
||
>付费API密钥</label
|
||
>
|
||
<input
|
||
type="text"
|
||
id="PAID_KEY"
|
||
name="PAID_KEY"
|
||
placeholder="AIzaSyxxxxxxxxxxxxxxxxxxx"
|
||
class="w-full px-4 py-3 rounded-lg border border-gray-300 focus:border-primary-500 focus:ring focus:ring-primary-200 focus:ring-opacity-50 sensitive-input"
|
||
/>
|
||
<small class="text-gray-500 mt-1 block"
|
||
>用于图像生成的付费API密钥</small
|
||
>
|
||
</div>
|
||
|
||
<!-- 图像生成模型 -->
|
||
<div class="mb-6">
|
||
<label
|
||
for="CREATE_IMAGE_MODEL"
|
||
class="block font-semibold mb-2 text-gray-700"
|
||
>图像生成模型</label
|
||
>
|
||
<input
|
||
type="text"
|
||
id="CREATE_IMAGE_MODEL"
|
||
name="CREATE_IMAGE_MODEL"
|
||
placeholder="imagen-3.0-generate-002"
|
||
class="w-full px-4 py-3 rounded-lg border border-gray-300 focus:border-primary-500 focus:ring focus:ring-primary-200 focus:ring-opacity-50"
|
||
/>
|
||
<small class="text-gray-500 mt-1 block">用于图像生成的模型</small>
|
||
</div>
|
||
|
||
<!-- 上传提供商 -->
|
||
<div class="mb-6">
|
||
<label
|
||
for="UPLOAD_PROVIDER"
|
||
class="block font-semibold mb-2 text-gray-700"
|
||
>上传提供商</label
|
||
>
|
||
<select
|
||
id="UPLOAD_PROVIDER"
|
||
name="UPLOAD_PROVIDER"
|
||
class="w-full px-4 py-3 rounded-lg border border-gray-300 focus:border-primary-500 focus:ring focus:ring-primary-200 focus:ring-opacity-50 bg-white"
|
||
>
|
||
<option value="smms" selected>SM.MS</option>
|
||
<option value="picgo">PicGo</option>
|
||
<option value="cloudflare_imgbed">Cloudflare</option>
|
||
</select>
|
||
<small class="text-gray-500 mt-1 block">图片上传服务提供商</small>
|
||
</div>
|
||
|
||
<!-- SM.MS密钥 -->
|
||
<div class="mb-6 provider-config active" data-provider="smms">
|
||
<label
|
||
for="SMMS_SECRET_TOKEN"
|
||
class="block font-semibold mb-2 text-gray-700"
|
||
>SM.MS密钥</label
|
||
>
|
||
<input
|
||
type="text"
|
||
id="SMMS_SECRET_TOKEN"
|
||
name="SMMS_SECRET_TOKEN"
|
||
placeholder="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
|
||
class="w-full px-4 py-3 rounded-lg border border-gray-300 focus:border-primary-500 focus:ring focus:ring-primary-200 focus:ring-opacity-50 sensitive-input"
|
||
/>
|
||
<small class="text-gray-500 mt-1 block">SM.MS图床的密钥</small>
|
||
</div>
|
||
|
||
<!-- PicGo API密钥 -->
|
||
<div class="mb-6 provider-config" data-provider="picgo">
|
||
<label
|
||
for="PICGO_API_KEY"
|
||
class="block font-semibold mb-2 text-gray-700"
|
||
>PicGo API密钥</label
|
||
>
|
||
<input
|
||
type="text"
|
||
id="PICGO_API_KEY"
|
||
name="PICGO_API_KEY"
|
||
placeholder="xxxx"
|
||
class="w-full px-4 py-3 rounded-lg border border-gray-300 focus:border-primary-500 focus:ring focus:ring-primary-200 focus:ring-opacity-50 sensitive-input"
|
||
/>
|
||
<small class="text-gray-500 mt-1 block">PicGo的API密钥</small>
|
||
</div>
|
||
|
||
<!-- Cloudflare图床URL -->
|
||
<div class="mb-6 provider-config" data-provider="cloudflare_imgbed">
|
||
<label
|
||
for="CLOUDFLARE_IMGBED_URL"
|
||
class="block font-semibold mb-2 text-gray-700"
|
||
>Cloudflare图床URL</label
|
||
>
|
||
<input
|
||
type="text"
|
||
id="CLOUDFLARE_IMGBED_URL"
|
||
name="CLOUDFLARE_IMGBED_URL"
|
||
placeholder="https://xxxxxxx.pages.dev/upload"
|
||
class="w-full px-4 py-3 rounded-lg border border-gray-300 focus:border-primary-500 focus:ring focus:ring-primary-200 focus:ring-opacity-50"
|
||
/>
|
||
<small class="text-gray-500 mt-1 block">Cloudflare图床的URL</small>
|
||
</div>
|
||
|
||
<!-- Cloudflare认证码 -->
|
||
<div class="mb-6 provider-config" data-provider="cloudflare_imgbed">
|
||
<label
|
||
for="CLOUDFLARE_IMGBED_AUTH_CODE"
|
||
class="block font-semibold mb-2 text-gray-700"
|
||
>Cloudflare认证码</label
|
||
>
|
||
<input
|
||
type="text"
|
||
id="CLOUDFLARE_IMGBED_AUTH_CODE"
|
||
name="CLOUDFLARE_IMGBED_AUTH_CODE"
|
||
placeholder="xxxxxxxxx"
|
||
class="w-full px-4 py-3 rounded-lg border border-gray-300 focus:border-primary-500 focus:ring focus:ring-primary-200 focus:ring-opacity-50 sensitive-input"
|
||
/>
|
||
<small class="text-gray-500 mt-1 block">Cloudflare图床的认证码</small>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 流式输出优化器配置 -->
|
||
<div
|
||
class="config-section bg-white bg-opacity-70 rounded-xl p-6 mb-6 shadow-lg"
|
||
id="stream-section"
|
||
>
|
||
<h2
|
||
class="text-xl font-bold mb-6 pb-3 border-b border-gray-200 flex items-center gap-2"
|
||
>
|
||
<i class="fas fa-stream text-primary-600"></i> 流式输出优化器
|
||
</h2>
|
||
|
||
<!-- 启用流式输出优化 -->
|
||
<div class="mb-6 flex items-center justify-between">
|
||
<label
|
||
for="STREAM_OPTIMIZER_ENABLED"
|
||
class="font-semibold text-gray-700"
|
||
>启用流式输出优化</label
|
||
>
|
||
<div
|
||
class="relative inline-block w-10 mr-2 align-middle select-none transition duration-200 ease-in"
|
||
>
|
||
<input
|
||
type="checkbox"
|
||
name="STREAM_OPTIMIZER_ENABLED"
|
||
id="STREAM_OPTIMIZER_ENABLED"
|
||
class="toggle-checkbox absolute block w-6 h-6 rounded-full bg-white border-4 appearance-none cursor-pointer"
|
||
/>
|
||
<label
|
||
for="STREAM_OPTIMIZER_ENABLED"
|
||
class="toggle-label block overflow-hidden h-6 rounded-full bg-gray-300 cursor-pointer"
|
||
></label>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 最小延迟 -->
|
||
<div class="mb-6">
|
||
<label
|
||
for="STREAM_MIN_DELAY"
|
||
class="block font-semibold mb-2 text-gray-700"
|
||
>最小延迟(秒)</label
|
||
>
|
||
<input
|
||
type="number"
|
||
id="STREAM_MIN_DELAY"
|
||
name="STREAM_MIN_DELAY"
|
||
min="0"
|
||
max="1"
|
||
step="0.001"
|
||
class="w-full px-4 py-3 rounded-lg border border-gray-300 focus:border-primary-500 focus:ring focus:ring-primary-200 focus:ring-opacity-50"
|
||
/>
|
||
<small class="text-gray-500 mt-1 block">流式输出的最小延迟时间</small>
|
||
</div>
|
||
|
||
<!-- 最大延迟 -->
|
||
<div class="mb-6">
|
||
<label
|
||
for="STREAM_MAX_DELAY"
|
||
class="block font-semibold mb-2 text-gray-700"
|
||
>最大延迟(秒)</label
|
||
>
|
||
<input
|
||
type="number"
|
||
id="STREAM_MAX_DELAY"
|
||
name="STREAM_MAX_DELAY"
|
||
min="0"
|
||
max="1"
|
||
step="0.001"
|
||
class="w-full px-4 py-3 rounded-lg border border-gray-300 focus:border-primary-500 focus:ring focus:ring-primary-200 focus:ring-opacity-50"
|
||
/>
|
||
<small class="text-gray-500 mt-1 block">流式输出的最大延迟时间</small>
|
||
</div>
|
||
|
||
<!-- 短文本阈值 -->
|
||
<div class="mb-6">
|
||
<label
|
||
for="STREAM_SHORT_TEXT_THRESHOLD"
|
||
class="block font-semibold mb-2 text-gray-700"
|
||
>短文本阈值</label
|
||
>
|
||
<input
|
||
type="number"
|
||
id="STREAM_SHORT_TEXT_THRESHOLD"
|
||
name="STREAM_SHORT_TEXT_THRESHOLD"
|
||
min="1"
|
||
max="100"
|
||
class="w-full px-4 py-3 rounded-lg border border-gray-300 focus:border-primary-500 focus:ring focus:ring-primary-200 focus:ring-opacity-50"
|
||
/>
|
||
<small class="text-gray-500 mt-1 block">短文本的字符阈值</small>
|
||
</div>
|
||
|
||
<!-- 长文本阈值 -->
|
||
<div class="mb-6">
|
||
<label
|
||
for="STREAM_LONG_TEXT_THRESHOLD"
|
||
class="block font-semibold mb-2 text-gray-700"
|
||
>长文本阈值</label
|
||
>
|
||
<input
|
||
type="number"
|
||
id="STREAM_LONG_TEXT_THRESHOLD"
|
||
name="STREAM_LONG_TEXT_THRESHOLD"
|
||
min="1"
|
||
max="1000"
|
||
class="w-full px-4 py-3 rounded-lg border border-gray-300 focus:border-primary-500 focus:ring focus:ring-primary-200 focus:ring-opacity-50"
|
||
/>
|
||
<small class="text-gray-500 mt-1 block">长文本的字符阈值</small>
|
||
</div>
|
||
|
||
<!-- 分块大小 -->
|
||
<div class="mb-6">
|
||
<label
|
||
for="STREAM_CHUNK_SIZE"
|
||
class="block font-semibold mb-2 text-gray-700"
|
||
>分块大小</label
|
||
>
|
||
<input
|
||
type="number"
|
||
id="STREAM_CHUNK_SIZE"
|
||
name="STREAM_CHUNK_SIZE"
|
||
min="1"
|
||
max="100"
|
||
class="w-full px-4 py-3 rounded-lg border border-gray-300 focus:border-primary-500 focus:ring focus:ring-primary-200 focus:ring-opacity-50"
|
||
/>
|
||
<small class="text-gray-500 mt-1 block">流式输出的分块大小</small>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 定时任务配置 -->
|
||
<div
|
||
class="config-section bg-white bg-opacity-70 rounded-xl p-6 mb-6 shadow-lg"
|
||
id="scheduler-section"
|
||
>
|
||
<h2
|
||
class="text-xl font-bold mb-6 pb-3 border-b border-gray-200 flex items-center gap-2"
|
||
>
|
||
<i class="fas fa-clock text-primary-600"></i> 定时任务配置
|
||
</h2>
|
||
|
||
<!-- 检查间隔 -->
|
||
<div class="mb-6">
|
||
<label
|
||
for="CHECK_INTERVAL_HOURS"
|
||
class="block font-semibold mb-2 text-gray-700"
|
||
>检查间隔(小时)</label
|
||
>
|
||
<input
|
||
type="number"
|
||
id="CHECK_INTERVAL_HOURS"
|
||
name="CHECK_INTERVAL_HOURS"
|
||
min="1"
|
||
class="w-full px-4 py-3 rounded-lg border border-gray-300 focus:border-primary-500 focus:ring focus:ring-primary-200 focus:ring-opacity-50"
|
||
/>
|
||
<small class="text-gray-500 mt-1 block"
|
||
>定时检查密钥状态的间隔时间(单位:小时)</small
|
||
>
|
||
</div>
|
||
|
||
<!-- 时区 -->
|
||
<div class="mb-6">
|
||
<label for="TIMEZONE" class="block font-semibold mb-2 text-gray-700"
|
||
>时区</label
|
||
>
|
||
<input
|
||
type="text"
|
||
id="TIMEZONE"
|
||
name="TIMEZONE"
|
||
placeholder="例如: Asia/Shanghai"
|
||
class="w-full px-4 py-3 rounded-lg border border-gray-300 focus:border-primary-500 focus:ring focus:ring-primary-200 focus:ring-opacity-50"
|
||
/>
|
||
<small class="text-gray-500 mt-1 block"
|
||
>定时任务使用的时区,格式如 "Asia/Shanghai" 或 "UTC"</small
|
||
>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 日志配置 -->
|
||
<div
|
||
class="config-section bg-white bg-opacity-70 rounded-xl p-6 mb-6 shadow-lg"
|
||
id="logging-section"
|
||
>
|
||
<h2
|
||
class="text-xl font-bold mb-6 pb-3 border-b border-gray-200 flex items-center gap-2"
|
||
>
|
||
<i class="fas fa-file-alt text-primary-600"></i> 日志配置
|
||
</h2>
|
||
|
||
<!-- 日志级别 -->
|
||
<div class="mb-6">
|
||
<label for="LOG_LEVEL" class="block font-semibold mb-2 text-gray-700"
|
||
>日志级别</label
|
||
>
|
||
<select
|
||
id="LOG_LEVEL"
|
||
name="LOG_LEVEL"
|
||
class="w-full px-4 py-3 rounded-lg border border-gray-300 focus:border-primary-500 focus:ring focus:ring-primary-200 focus:ring-opacity-50 bg-white"
|
||
>
|
||
<option value="DEBUG">DEBUG</option>
|
||
<option value="INFO">INFO</option>
|
||
<option value="WARNING">WARNING</option>
|
||
<option value="ERROR">ERROR</option>
|
||
<option value="CRITICAL">CRITICAL</option>
|
||
</select>
|
||
<small class="text-gray-500 mt-1 block"
|
||
>设置应用程序的日志记录详细程度</small
|
||
>
|
||
</div>
|
||
|
||
<!-- 自动删除错误日志 -->
|
||
<div class="mb-6">
|
||
<div class="flex items-center justify-between">
|
||
<label
|
||
for="AUTO_DELETE_ERROR_LOGS_ENABLED"
|
||
class="font-semibold text-gray-700"
|
||
>是否开启自动删除错误日志</label
|
||
>
|
||
<div
|
||
class="relative inline-block w-10 mr-2 align-middle select-none transition duration-200 ease-in"
|
||
>
|
||
<input
|
||
type="checkbox"
|
||
name="AUTO_DELETE_ERROR_LOGS_ENABLED"
|
||
id="AUTO_DELETE_ERROR_LOGS_ENABLED"
|
||
class="toggle-checkbox absolute block w-6 h-6 rounded-full bg-white border-4 appearance-none cursor-pointer"
|
||
/>
|
||
<label
|
||
for="AUTO_DELETE_ERROR_LOGS_ENABLED"
|
||
class="toggle-label block overflow-hidden h-6 rounded-full bg-gray-300 cursor-pointer"
|
||
></label>
|
||
</div>
|
||
</div>
|
||
<small class="text-gray-500 mt-1 block"
|
||
>开启后,将自动删除指定天数前的错误日志。</small
|
||
>
|
||
</div>
|
||
|
||
<!-- 自动删除日志天数 -->
|
||
<div class="mb-6">
|
||
<label
|
||
for="AUTO_DELETE_ERROR_LOGS_DAYS"
|
||
class="block font-semibold mb-2 text-gray-700"
|
||
>自动删除多少天前的错误日志</label
|
||
>
|
||
<select
|
||
id="AUTO_DELETE_ERROR_LOGS_DAYS"
|
||
name="AUTO_DELETE_ERROR_LOGS_DAYS"
|
||
class="w-full px-4 py-3 rounded-lg border border-gray-300 focus:border-primary-500 focus:ring focus:ring-primary-200 focus:ring-opacity-50 bg-white"
|
||
>
|
||
<option value="1">1 天</option>
|
||
<option value="7">7 天</option>
|
||
<option value="30">30 天</option>
|
||
</select>
|
||
<small class="text-gray-500 mt-1 block"
|
||
>选择自动删除错误日志的天数。</small
|
||
>
|
||
</div>
|
||
|
||
<!-- 自动删除请求日志 -->
|
||
<div class="mb-6">
|
||
<div class="flex items-center justify-between">
|
||
<label
|
||
for="AUTO_DELETE_REQUEST_LOGS_ENABLED"
|
||
class="font-semibold text-gray-700"
|
||
>是否开启自动删除请求日志</label
|
||
>
|
||
<div
|
||
class="relative inline-block w-10 mr-2 align-middle select-none transition duration-200 ease-in"
|
||
>
|
||
<input
|
||
type="checkbox"
|
||
name="AUTO_DELETE_REQUEST_LOGS_ENABLED"
|
||
id="AUTO_DELETE_REQUEST_LOGS_ENABLED"
|
||
class="toggle-checkbox absolute block w-6 h-6 rounded-full bg-white border-4 appearance-none cursor-pointer"
|
||
/>
|
||
<label
|
||
for="AUTO_DELETE_REQUEST_LOGS_ENABLED"
|
||
class="toggle-label block overflow-hidden h-6 rounded-full bg-gray-300 cursor-pointer"
|
||
></label>
|
||
</div>
|
||
</div>
|
||
<small class="text-gray-500 mt-1 block"
|
||
>开启后,将自动删除指定天数前的请求日志。</small
|
||
>
|
||
</div>
|
||
|
||
<!-- 自动删除请求日志天数 -->
|
||
<div class="mb-6">
|
||
<label
|
||
for="AUTO_DELETE_REQUEST_LOGS_DAYS"
|
||
class="block font-semibold mb-2 text-gray-700"
|
||
>自动删除多少天前的请求日志</label
|
||
>
|
||
<select
|
||
id="AUTO_DELETE_REQUEST_LOGS_DAYS"
|
||
name="AUTO_DELETE_REQUEST_LOGS_DAYS"
|
||
class="w-full px-4 py-3 rounded-lg border border-gray-300 focus:border-primary-500 focus:ring focus:ring-primary-200 focus:ring-opacity-50 bg-white"
|
||
>
|
||
<option value="1">1 天</option>
|
||
<option value="7">7 天</option>
|
||
<option value="30">30 天</option>
|
||
</select>
|
||
<small class="text-gray-500 mt-1 block"
|
||
>选择自动删除请求日志的天数。</small
|
||
>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Action Buttons -->
|
||
<div class="flex flex-col md:flex-row justify-center gap-4 mt-8">
|
||
<button
|
||
type="button"
|
||
id="saveBtn"
|
||
class="bg-gradient-to-r from-primary-600 to-primary-700 text-white px-8 py-3 rounded-xl font-semibold transition-all duration-300 transform hover:-translate-y-1 hover:shadow-lg flex items-center justify-center gap-2"
|
||
>
|
||
<i class="fas fa-save"></i> 保存配置
|
||
</button>
|
||
<button
|
||
type="button"
|
||
id="resetBtn"
|
||
class="bg-gradient-to-r from-gray-400 to-gray-500 text-white px-8 py-3 rounded-xl font-semibold transition-all duration-300 transform hover:-translate-y-1 hover:shadow-lg flex items-center justify-center gap-2"
|
||
>
|
||
<i class="fas fa-undo"></i> 重置配置
|
||
</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Scroll buttons are now in base.html -->
|
||
<div class="scroll-buttons">
|
||
<button class="scroll-button" onclick="scrollToTop()" title="回到顶部">
|
||
<i class="fas fa-chevron-up"></i>
|
||
</button>
|
||
<button class="scroll-button" onclick="scrollToBottom()" title="滚动到底部">
|
||
<i class="fas fa-chevron-down"></i>
|
||
</button>
|
||
</div>
|
||
|
||
<!-- Notification component is now in base.html -->
|
||
<div id="notification" class="notification"></div>
|
||
<!-- Footer is now in base.html -->
|
||
|
||
<!-- API Key Add Modal -->
|
||
<div id="apiKeyModal" class="modal">
|
||
<div
|
||
class="w-full max-w-lg mx-auto bg-white rounded-2xl shadow-2xl overflow-hidden animate-fade-in"
|
||
>
|
||
<div class="p-6">
|
||
<div class="flex justify-between items-center mb-4">
|
||
<h2 class="text-xl font-bold text-gray-800">批量添加 API 密钥</h2>
|
||
<button
|
||
id="closeApiKeyModalBtn"
|
||
class="text-gray-400 hover:text-gray-600 text-xl"
|
||
>
|
||
×
|
||
</button>
|
||
</div>
|
||
<p class="text-gray-600 mb-4">
|
||
每行粘贴一个或多个密钥,将自动提取有效密钥并去重。
|
||
</p>
|
||
<textarea
|
||
id="apiKeyBulkInput"
|
||
rows="10"
|
||
placeholder="在此处粘贴 API 密钥..."
|
||
class="w-full px-4 py-3 rounded-lg border border-gray-300 focus:border-primary-500 focus:ring focus:ring-primary-200 focus:ring-opacity-50 font-mono text-sm"
|
||
></textarea>
|
||
<div class="flex justify-end gap-3 mt-6">
|
||
<button
|
||
type="button"
|
||
id="confirmAddApiKeyBtn"
|
||
class="bg-primary-600 hover:bg-primary-700 text-white px-6 py-2 rounded-lg font-medium transition"
|
||
>
|
||
确认添加
|
||
</button>
|
||
<button
|
||
type="button"
|
||
id="cancelAddApiKeyBtn"
|
||
class="bg-gray-200 hover:bg-gray-300 text-gray-700 px-6 py-2 rounded-lg font-medium transition"
|
||
>
|
||
取消
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Bulk Delete API Key Modal -->
|
||
<div id="bulkDeleteApiKeyModal" class="modal">
|
||
<div
|
||
class="w-full max-w-lg mx-auto bg-white rounded-2xl shadow-2xl overflow-hidden animate-fade-in"
|
||
>
|
||
<div class="p-6">
|
||
<div class="flex justify-between items-center mb-4">
|
||
<h2 class="text-xl font-bold text-gray-800">批量删除 API 密钥</h2>
|
||
<button
|
||
id="closeBulkDeleteModalBtn"
|
||
class="text-gray-400 hover:text-gray-600 text-xl"
|
||
>
|
||
×
|
||
</button>
|
||
</div>
|
||
<p class="text-gray-600 mb-4">
|
||
每行粘贴一个或多个密钥,将自动提取有效密钥并从列表中删除。
|
||
</p>
|
||
<textarea
|
||
id="bulkDeleteApiKeyInput"
|
||
rows="10"
|
||
placeholder="在此处粘贴要删除的 API 密钥..."
|
||
class="w-full px-4 py-3 rounded-lg border border-gray-300 focus:border-danger-500 focus:ring focus:ring-danger-200 focus:ring-opacity-50 font-mono text-sm"
|
||
></textarea>
|
||
<div class="flex justify-end gap-3 mt-6">
|
||
<button
|
||
type="button"
|
||
id="confirmBulkDeleteApiKeyBtn"
|
||
class="bg-danger-600 hover:bg-danger-700 text-white px-6 py-2 rounded-lg font-medium transition"
|
||
>
|
||
确认删除
|
||
</button>
|
||
<button
|
||
type="button"
|
||
id="cancelBulkDeleteApiKeyBtn"
|
||
class="bg-gray-200 hover:bg-gray-300 text-gray-700 px-6 py-2 rounded-lg font-medium transition"
|
||
>
|
||
取消
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Proxy Add Modal -->
|
||
<div id="proxyModal" class="modal">
|
||
<div
|
||
class="w-full max-w-lg mx-auto bg-white rounded-2xl shadow-2xl overflow-hidden animate-fade-in"
|
||
>
|
||
<div class="p-6">
|
||
<div class="flex justify-between items-center mb-4">
|
||
<h2 class="text-xl font-bold text-gray-800">批量添加代理服务器</h2>
|
||
<button
|
||
id="closeProxyModalBtn"
|
||
class="text-gray-400 hover:text-gray-600 text-xl"
|
||
>
|
||
×
|
||
</button>
|
||
</div>
|
||
<p class="text-gray-600 mb-4">
|
||
每行粘贴一个或多个代理地址,将自动提取有效地址并去重。
|
||
</p>
|
||
<textarea
|
||
id="proxyBulkInput"
|
||
rows="10"
|
||
placeholder="在此处粘贴代理地址 (例如 http://user:pass@host:port 或 socks5://host:port)..."
|
||
class="w-full px-4 py-3 rounded-lg border border-gray-300 focus:border-primary-500 focus:ring focus:ring-primary-200 focus:ring-opacity-50 font-mono text-sm"
|
||
></textarea>
|
||
<div class="flex justify-end gap-3 mt-6">
|
||
<button
|
||
type="button"
|
||
id="confirmAddProxyBtn"
|
||
class="bg-primary-600 hover:bg-primary-700 text-white px-6 py-2 rounded-lg font-medium transition"
|
||
>
|
||
确认添加
|
||
</button>
|
||
<button
|
||
type="button"
|
||
id="cancelAddProxyBtn"
|
||
class="bg-gray-200 hover:bg-gray-300 text-gray-700 px-6 py-2 rounded-lg font-medium transition"
|
||
>
|
||
取消
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Bulk Delete Proxy Modal -->
|
||
<div id="bulkDeleteProxyModal" class="modal">
|
||
<div
|
||
class="w-full max-w-lg mx-auto bg-white rounded-2xl shadow-2xl overflow-hidden animate-fade-in"
|
||
>
|
||
<div class="p-6">
|
||
<div class="flex justify-between items-center mb-4">
|
||
<h2 class="text-xl font-bold text-gray-800">批量删除代理服务器</h2>
|
||
<button
|
||
id="closeBulkDeleteProxyModalBtn"
|
||
class="text-gray-400 hover:text-gray-600 text-xl"
|
||
>
|
||
×
|
||
</button>
|
||
</div>
|
||
<p class="text-gray-600 mb-4">
|
||
每行粘贴一个或多个代理地址,将自动提取有效地址并从列表中删除。
|
||
</p>
|
||
<textarea
|
||
id="bulkDeleteProxyInput"
|
||
rows="10"
|
||
placeholder="在此处粘贴要删除的代理地址..."
|
||
class="w-full px-4 py-3 rounded-lg border border-gray-300 focus:border-danger-500 focus:ring focus:ring-danger-200 focus:ring-opacity-50 font-mono text-sm"
|
||
></textarea>
|
||
<div class="flex justify-end gap-3 mt-6">
|
||
<button
|
||
type="button"
|
||
id="confirmBulkDeleteProxyBtn"
|
||
class="bg-danger-600 hover:bg-danger-700 text-white px-6 py-2 rounded-lg font-medium transition"
|
||
>
|
||
确认删除
|
||
</button>
|
||
<button
|
||
type="button"
|
||
id="cancelBulkDeleteProxyBtn"
|
||
class="bg-gray-200 hover:bg-gray-300 text-gray-700 px-6 py-2 rounded-lg font-medium transition"
|
||
>
|
||
取消
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Reset Confirmation Modal -->
|
||
<div id="resetConfirmModal" class="modal">
|
||
<div
|
||
class="w-full max-w-md mx-auto bg-white rounded-2xl shadow-2xl overflow-hidden animate-fade-in"
|
||
>
|
||
<div class="p-6">
|
||
<div class="flex justify-between items-center mb-4">
|
||
<h2 class="text-xl font-bold text-gray-800">确认重置配置</h2>
|
||
<button
|
||
id="closeResetModalBtn"
|
||
class="text-gray-400 hover:text-gray-600 text-xl"
|
||
>
|
||
×
|
||
</button>
|
||
</div>
|
||
<p class="text-gray-600 mb-6">
|
||
确定要重置所有配置吗?<br />这将恢复到默认值,此操作不可撤销。
|
||
</p>
|
||
<div class="flex justify-end gap-3">
|
||
<button
|
||
type="button"
|
||
id="confirmResetBtn"
|
||
class="bg-red-500 hover:bg-red-600 text-white px-6 py-2 rounded-lg font-medium transition"
|
||
>
|
||
确认重置
|
||
</button>
|
||
<button
|
||
type="button"
|
||
id="cancelResetBtn"
|
||
class="bg-primary-600 hover:bg-primary-700 text-white px-6 py-2 rounded-lg font-medium transition"
|
||
>
|
||
取消
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{% endblock %} {% block body_scripts %}
|
||
<script src="/static/js/config_editor.js"></script>
|
||
<!-- Add any other page-specific JS initialization here if needed -->
|
||
{% endblock %}
|