mirror of
https://github.com/snailyp/gemini-balance.git
synced 2026-09-09 01:46:38 +08:00
refactor: 重构密钥状态页面为客户端动态加载
- 新增 key_routes.py 分离密钥相关路由逻辑 - 将密钥列表从服务器端渲染改为 JavaScript 动态加载 - 优化 keys_status 页面错误处理,提供默认数据结构 - 在 KeyManager 中添加 get_all_keys_with_fail_count 方法 - 移除服务器端模板中的静态密钥渲染代码 这次重构提升了页面加载性能和用户体验,同时改善了错误处理机制。
This commit is contained in:
@@ -1319,95 +1319,10 @@ endblock %} {% block head_extra_styles %}
|
||||
<div class="key-content p-4 bg-white bg-opacity-40">
|
||||
<!-- Key list will be populated by JS -->
|
||||
<ul id="validKeys" class="grid grid-cols-1 md:grid-cols-2 gap-3">
|
||||
{# Initial keys rendered by server-side for non-JS users or initial
|
||||
load #} {# JS will replace this content with paginated/filtered
|
||||
results #} {% if valid_keys %} {% for key, fail_count in
|
||||
valid_keys.items() %}
|
||||
<li
|
||||
class="bg-white rounded-lg p-3 shadow-sm hover:shadow-md transition-all duration-300 border border-gray-100 hover:border-success-300 transform hover:-translate-y-1"
|
||||
data-fail-count="{{ fail_count }}"
|
||||
data-key="{{ key }}"
|
||||
>
|
||||
<!-- Checkbox -->
|
||||
<input
|
||||
type="checkbox"
|
||||
class="form-checkbox h-5 w-5 text-primary-600 border-gray-300 rounded focus:ring-primary-500 mt-1 key-checkbox"
|
||||
data-key-type="valid"
|
||||
value="{{ key }}"
|
||||
/>
|
||||
<!-- Key Info -->
|
||||
<div class="flex-grow">
|
||||
<div class="flex flex-col justify-between h-full gap-3">
|
||||
<div class="flex flex-wrap items-center gap-2">
|
||||
<span
|
||||
class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-success-50 text-success-600"
|
||||
>
|
||||
<i class="fas fa-check mr-1"></i> 有效
|
||||
</span>
|
||||
<div class="flex items-center gap-1">
|
||||
<span class="key-text font-mono" data-full-key="{{ key }}"
|
||||
>{{ key[:4] + '...' + key[-4:] }}</span
|
||||
>
|
||||
<button
|
||||
class="text-gray-500 hover:text-primary-600 transition-colors"
|
||||
onclick="toggleKeyVisibility(this)"
|
||||
title="显示/隐藏密钥"
|
||||
>
|
||||
<i class="fas fa-eye"></i>
|
||||
</button>
|
||||
</div>
|
||||
<span
|
||||
class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-amber-50 text-amber-600"
|
||||
>
|
||||
<i class="fas fa-exclamation-triangle mr-1"></i>
|
||||
失败: {{ fail_count }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex flex-wrap items-center gap-2">
|
||||
<button
|
||||
class="flex items-center gap-1 bg-success-600 hover:bg-success-700 text-white px-2.5 py-1 rounded-lg text-xs font-medium transition-all duration-200"
|
||||
onclick="verifyKey('{{ key }}', this)"
|
||||
>
|
||||
<i class="fas fa-check-circle"></i>
|
||||
验证
|
||||
</button>
|
||||
<button
|
||||
class="flex items-center gap-1 bg-gray-500 hover:bg-gray-600 text-white px-2.5 py-1 rounded-lg text-xs font-medium transition-all duration-200"
|
||||
onclick="resetKeyFailCount('{{ key }}', this)"
|
||||
>
|
||||
<i class="fas fa-redo-alt"></i>
|
||||
重置
|
||||
</button>
|
||||
<button
|
||||
class="flex items-center gap-1 bg-blue-500 hover:bg-blue-600 text-white px-2.5 py-1 rounded-lg text-xs font-medium transition-all duration-200"
|
||||
onclick="copyKey('{{ key }}')"
|
||||
>
|
||||
<i class="fas fa-copy"></i>
|
||||
复制
|
||||
</button>
|
||||
<button
|
||||
class="flex items-center gap-1 bg-blue-600 hover:bg-blue-700 text-white px-2.5 py-1 rounded-lg text-xs font-medium transition-all duration-200"
|
||||
onclick="showKeyUsageDetails('{{ key }}')"
|
||||
>
|
||||
<i class="fas fa-chart-pie"></i>
|
||||
详情
|
||||
</button>
|
||||
<button
|
||||
class="flex items-center gap-1 bg-red-800 hover:bg-red-900 text-white px-2.5 py-1 rounded-lg text-xs font-medium transition-all duration-200"
|
||||
onclick="showSingleKeyDeleteConfirmModal('{{ key }}', this)"
|
||||
>
|
||||
<i class="fas fa-trash-alt"></i>
|
||||
删除
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{% endfor %} {% else %}
|
||||
{# This content is now loaded via JavaScript #}
|
||||
<li class="text-center text-gray-500 py-4 col-span-full">
|
||||
暂无有效密钥
|
||||
<i class="fas fa-spinner fa-spin"></i> Loading keys...
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
<!-- 有效密钥分页控件容器 -->
|
||||
<div
|
||||
@@ -1503,93 +1418,10 @@ endblock %} {% block head_extra_styles %}
|
||||
<div class="key-content p-4 bg-white bg-opacity-40">
|
||||
<!-- Key list will be populated by JS -->
|
||||
<ul id="invalidKeys" class="grid grid-cols-1 md:grid-cols-2 gap-3">
|
||||
{# Initial keys rendered by server-side #} {# JS will replace this
|
||||
content with paginated results #} {% if invalid_keys %} {% for key,
|
||||
fail_count in invalid_keys.items() %}
|
||||
<li
|
||||
class="bg-white rounded-lg p-3 shadow-sm hover:shadow-md transition-all duration-300 border border-gray-100 hover:border-danger-300 transform hover:-translate-y-1"
|
||||
data-key="{{ key }}"
|
||||
>
|
||||
<!-- Checkbox -->
|
||||
<input
|
||||
type="checkbox"
|
||||
class="form-checkbox h-5 w-5 text-primary-600 border-gray-300 rounded focus:ring-primary-500 mt-1 key-checkbox"
|
||||
data-key-type="invalid"
|
||||
value="{{ key }}"
|
||||
/>
|
||||
<!-- Key Info -->
|
||||
<div class="flex-grow">
|
||||
<div class="flex flex-col justify-between h-full gap-3">
|
||||
<div class="flex flex-wrap items-center gap-2">
|
||||
<span
|
||||
class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-danger-50 text-danger-600"
|
||||
>
|
||||
<i class="fas fa-times mr-1"></i> 无效
|
||||
</span>
|
||||
<div class="flex items-center gap-1">
|
||||
<span class="key-text font-mono" data-full-key="{{ key }}"
|
||||
>{{ key[:4] + '...' + key[-4:] }}</span
|
||||
>
|
||||
<button
|
||||
class="text-gray-500 hover:text-primary-600 transition-colors"
|
||||
onclick="toggleKeyVisibility(this)"
|
||||
title="显示/隐藏密钥"
|
||||
>
|
||||
<i class="fas fa-eye"></i>
|
||||
</button>
|
||||
</div>
|
||||
<span
|
||||
class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-amber-50 text-amber-600"
|
||||
>
|
||||
<i class="fas fa-exclamation-triangle mr-1"></i>
|
||||
失败: {{ fail_count }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex flex-wrap items-center gap-2">
|
||||
<button
|
||||
class="flex items-center gap-1 bg-success-600 hover:bg-success-700 text-white px-2.5 py-1 rounded-lg text-xs font-medium transition-all duration-200"
|
||||
onclick="verifyKey('{{ key }}', this)"
|
||||
>
|
||||
<i class="fas fa-check-circle"></i>
|
||||
验证
|
||||
</button>
|
||||
<button
|
||||
class="flex items-center gap-1 bg-gray-500 hover:bg-gray-600 text-white px-2.5 py-1 rounded-lg text-xs font-medium transition-all duration-200"
|
||||
onclick="resetKeyFailCount('{{ key }}', this)"
|
||||
>
|
||||
<i class="fas fa-redo-alt"></i>
|
||||
重置
|
||||
</button>
|
||||
<button
|
||||
class="flex items-center gap-1 bg-blue-500 hover:bg-blue-600 text-white px-2.5 py-1 rounded-lg text-xs font-medium transition-all duration-200"
|
||||
onclick="copyKey('{{ key }}')"
|
||||
>
|
||||
<i class="fas fa-copy"></i>
|
||||
复制
|
||||
</button>
|
||||
<button
|
||||
class="flex items-center gap-1 bg-blue-600 hover:bg-blue-700 text-white px-2.5 py-1 rounded-lg text-xs font-medium transition-all duration-200"
|
||||
onclick="showKeyUsageDetails('{{ key }}')"
|
||||
>
|
||||
<i class="fas fa-chart-pie"></i>
|
||||
详情
|
||||
</button>
|
||||
<button
|
||||
class="flex items-center gap-1 bg-red-800 hover:bg-red-900 text-white px-2.5 py-1 rounded-lg text-xs font-medium transition-all duration-200"
|
||||
onclick="showSingleKeyDeleteConfirmModal('{{ key }}', this)"
|
||||
>
|
||||
<i class="fas fa-trash-alt"></i>
|
||||
删除
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{% endfor %} {% else %}
|
||||
{# This content is now loaded via JavaScript #}
|
||||
<li class="text-center text-gray-500 py-4 col-span-full">
|
||||
暂无无效密钥
|
||||
<i class="fas fa-spinner fa-spin"></i> Loading keys...
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
<!-- 无效密钥分页控件容器 -->
|
||||
<div
|
||||
|
||||
Reference in New Issue
Block a user