Files
gemini-banlancer/web/templates/logs.html
2025-11-26 20:36:25 +08:00

316 lines
21 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{% extends "base.html" %}
{% block title %}日志管理 - GEMINI BALANCER{% endblock %}
{% block content %}
<div class="w-full h-full flex flex-col pl-0 pr-3 lg:px-0" data-page-id="logs">
<!-- =================================================================== -->
<!-- 1. 页面顶栏:标题与全局控制器 -->
<!-- =================================================================== -->
<div class="flex items-center justify-between mb-4 shrink-0">
<div>
<h2 class="text-3xl font-bold tracking-tight">日志管理</h2>
<p class="text-sm text-zinc-500 dark:text-zinc-400 mt-1">查看、筛选和分析所有通过系统的请求记录。</p>
</div>
<div class="flex items-center space-x-2">
<!-- [新] 日志系统参数管理图标 -->
<button class="btn btn-icon" aria-label="日志设置">
<i class="fas fa-cog text-lg"></i>
</button>
</div>
</div>
<!-- =================================================================== -->
<!-- 2. 导航标签 -->
<!-- =================================================================== -->
<div class="py-2 shrink-0">
<div class="w-full overflow-x-auto scrollbar-hide">
<div role="tablist" class="relative inline-flex h-10 items-center justify-center inset-shadow-sm/25 rounded-lg bg-zinc-800/50 dark:bg-zinc-950 p-1" data-sliding-tabs-container>
<div class="absolute left-0 h-[calc(100%-0.5rem)] rounded-md bg-white dark:bg-zinc-700 shadow-sm" data-tab-indicator style="transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);"></div>
<a href="#" role="tab" class="tab-item tab-active" data-tab-item data-tab-target="error">错误日志</a>
<a href="#" role="tab" class="tab-item" data-tab-item data-tab-target="system">系统日志</a>
</div>
</div>
</div>
<!-- =================================================================== -->
<!-- 3. 主内容区:过滤器 + 表格 -->
<!-- =================================================================== -->
<div id="error-logs-filters" class="flex items-center justify-between shrink-0 py-4">
<div class="flex flex-1 items-center space-x-2">
<input id="log-search-input" class="input h-8 w-[150px] lg:w-[250px]" placeholder="全局模糊查找..." value="">
<button id="filter-error-type-btn" class="btn btn-outline border-dashed h-8 px-3 text-xs">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="mr-2 h-4 w-4">
<circle cx="12" cy="12" r="10"></circle><path d="M8 12h8"></path><path d="M12 8v8"></path>
</svg>
错误类型
</button>
<button id="filter-error-code-btn" class="btn btn-outline border-dashed h-8 px-3 text-xs">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="mr-2 h-4 w-4">
<circle cx="12" cy="12" r="10"></circle><path d="M8 12h8"></path><path d="M12 8v8"></path>
</svg>
错误码
</button>
<button id="filter-date-range-btn" class="btn btn-outline border-dashed h-8 px-3 text-xs">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="mr-2 h-4 w-4"><rect width="18" height="18" x="3" y="4" rx="2" ry="2"></rect><line x1="16" x2="16" y1="2" y2="6"></line><line x1="8" x2="8" y1="2" y2="6"></line><line x1="3" x2="21" y1="10" y2="10"></line></svg>
<span>时间范围</span>
</button>
</div>
<div class="relative inline-block text-left">
<div>
<button id="batch-actions-btn" type="button" class="btn btn-outline hidden lg:flex h-8 px-3 text-xs">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="mr-2 h-4 w-4">
<path d="M20 7h-9"></path><path d="M14 17H5"></path><circle cx="17" cy="17" r="3"></circle><circle cx="7" cy="7" r="3"></circle>
</svg>
批量操作
</button>
</div>
<!-- [ADDED] 下拉菜单的 HTML 结构 -->
<div id="batch-actions-menu" class="absolute right-0 z-30 mt-2 w-48 origin-top-right rounded-md bg-white dark:bg-zinc-800 shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none transition ease-out duration-100 transform opacity-0 scale-95 hidden" role="menu" aria-orientation="vertical" aria-labelledby="batch-actions-btn" tabindex="-1">
<div class="py-1" role="none">
<button id="delete-selected-logs-btn" class="flex items-center w-full px-4 py-2 text-sm text-foreground hover:bg-muted disabled:opacity-50 disabled:pointer-events-none" role="menuitem" tabindex="-1">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="mr-2 h-4 w-4 text-red-500"><path d="M3 6h18"></path><path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"></path><path d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"></path></svg>
<span>删除选定日志</span>
</button>
<button id="clear-all-logs-btn" class="flex items-center w-full px-4 py-2 text-sm text-foreground hover:bg-muted" role="menuitem" tabindex="-1">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="mr-2 h-4 w-4"><path d="m21.64 3.64-1.28-1.28a1.21 1.21 0 0 0-1.72 0L2.36 18.64a1.21 1.21 0 0 0 0 1.72l1.28 1.28a1.2 1.2 0 0 0 1.72 0L21.64 5.36a1.2 1.2 0 0 0 0-1.72Z"></path><path d="m14 7 3 3"></path><path d="M5 6v4h4"></path><path d="M19 14v4h-4"></path></svg>
<span>清除所有日志</span>
</button>
<button class="flex items-center w-full px-4 py-2 text-sm text-foreground hover:bg-muted" role="menuitem" tabindex="-1">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="mr-2 h-4 w-4"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path><polyline points="7 10 12 15 17 10"></polyline><line x1="12" x2="12" y1="15" y2="3"></line></svg>
<span>导出日志记录</span>
</button>
</div>
</div>
</div>
</div>
<!-- [新增] 3.2 系统日志的快捷操作栏 (默认隐藏) -->
<div id="system-logs-controls" class="hidden flex items-center justify-end shrink-0 py-4 space-x-4">
<div id="terminal-status-indicator" class="flex items-center text-xs text-zinc-500 dark:text-zinc-400">
<span class="relative flex h-2 w-2 mr-2">
<span class="animate-ping absolute inline-flex h-full w-full rounded-full bg-zinc-400 dark:bg-zinc-500 opacity-75"></span>
<span class="relative inline-flex rounded-full h-2 w-2 bg-zinc-500 dark:bg-zinc-600"></span>
</span>
未连接
</div>
<button data-action="toggle-connect-terminal" class="text-zinc-500 hover:text-zinc-700 dark:text-zinc-400 dark:hover:text-zinc-200" title="连接">
<i class="fas fa-plug h-4 w-4"></i>
</button>
<button data-action="clear-terminal" class="text-zinc-500 hover:text-zinc-700 dark:text-zinc-400 dark:hover:text-zinc-200" title="清屏">
<i class="fas fa-refresh h-4 w-4"></i>
</button>
<button data-action="toggle-pause-terminal" class="text-zinc-500 hover:text-zinc-700 dark:text-zinc-400 dark:hover:text-zinc-200" title="暂停">
<i class="fas fa-pause h-4 w-4"></i>
</button>
<button data-action="toggle-scroll-terminal" class="text-zinc-500 hover:text-zinc-700 dark:text-zinc-400 dark:hover:text-zinc-200" title="自动滚动">
<i class="fas fa-arrow-down h-4 w-4"></i>
</button>
<button data-action="terminal-settings" class="text-zinc-500 hover:text-zinc-700 dark:text-zinc-400 dark:hover:text-zinc-200" title="设置">
<i class="fas fa-sliders-h h-4 w-4"></i>
</button>
</div>
<!-- [修改] 3.3 核心内容容器,它的 *内部* 将被动态替换 -->
<div id="log-content-container" class="rounded-lg border border-zinc-200 dark:border-zinc-700 flex-grow overflow-hidden flex flex-col">
<!-- template 在这里切换 -->
</div>
</div>
<template id="error-logs-template">
<div class="relative w-full overflow-auto flex-grow main-content-scroll">
<table class="table">
<thead class="table-header">
<tr class="table-row">
<th class="table-head-cell w-4">
<input type="checkbox" class="h-4 w-4 rounded border-zinc-300 text-blue-600 focus:ring-blue-500">
</th>
<th class="table-head-cell w-16">序号</th>
<th class="table-head-cell">Gemini 密钥</th>
<th class="table-head-cell">群组名称</th>
<th class="table-head-cell">错误类型</th>
<th class="table-head-cell">状态码</th>
<th class="table-head-cell">模型名称</th>
<th class="table-head-cell">请求时间</th>
<th class="table-head-cell">操作</th>
</tr>
</thead>
<tbody class="table-body" id="logs-table-body">
<!-- JS will render content here -->
</tbody>
</table>
</div>
<!-- 分页控制器部分 -->
<div class="flex items-center justify-between p-2 shrink-0 border-t border-zinc-200 dark:border-zinc-700">
<div class="flex-1 text-sm text-zinc-500 dark:text-zinc-400">
已选择 <span class="font-semibold text-zinc-900 dark:text-white">0</span> / <span class="font-semibold text-zinc-900 dark:text-white">0</span>
</div>
<div class="flex items-center space-x-6 lg:space-x-8">
<div class="flex items-center space-x-2">
<p class="text-sm font-medium">每页行数</p>
<div data-component="custom-select-v2">
<button type="button" class="custom-select-trigger btn btn-secondary h-8 w-[70px] flex justify-between items-center px-2">
<span>20</span>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="h-4 w-4 opacity-50"><path d="m6 9 6 6 6-6"></path></svg>
</button>
<select class="hidden">
<option value="20" selected>20</option>
<option value="50">50</option>
<option value="100">100</option>
</select>
<template class="custom-select-panel-template">
<div class="custom-select-panel w-[70px] bg-white dark:bg-zinc-800 border border-zinc-200 dark:border-zinc-700 rounded-md shadow-lg z-[100]">
<!-- JS <select> -->
</div>
</template>
</div>
</div>
<div class="flex w-[100px] items-center justify-center text-sm font-medium">
第 1 / 1 页
</div>
<div class="flex items-center space-x-2" data-pagination-controls>
<button class="btn btn-secondary h-8 w-8 p-0 hidden lg:flex" disabled>
<span class="sr-only">Go to first page</span>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="h-4 w-4"><path d="m11 17-5-5 5-5"></path><path d="m18 17-5-5 5-5"></path></svg>
</button>
<button class="btn btn-secondary h-8 w-8 p-0" disabled>
<span class="sr-only">Go to previous page</span>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="h-4 w-4"><path d="m15 18-6-6 6-6"></path></svg>
</button>
<button class="btn btn-secondary h-8 w-8 p-0">
<span class="sr-only">Go to next page</span>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="h-4 w-4"><path d="m9 18 6-6-6-6"></path></svg>
</button>
<button class="btn btn-secondary h-8 w-8 p-0 hidden lg:flex">
<span class="sr-only">Go to last page</span>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="h-4 w-4"><path d="m6 17 5-5-5-5"></path><path d="m13 17 5-5-5-5"></path></svg>
</button>
</div>
</div>
</div>
</template>
<template id="system-logs-template">
<div id="log-terminal-output" class="w-full h-full overflow-y-auto main-content-scroll p-4 font-mono text-sm text-zinc-200 bg-zinc-900 dark:bg-black whitespace-pre-wrap break-all">
<!-- WebSocket 日志将在此处实时渲染 -->
</div>
</template>
{% endblock %}
{% block modals %}
<!-- [MODIFIED] 日志系统参数管理模态框 -->
<div id="log-settings-modal" class="modal-overlay hidden">
<div class="modal-panel max-w-2xl max-h-[90vh]">
<!-- Header -->
<div class="modal-header shrink-0">
<h2 id="log-settings-modal-title" class="modal-title">日志系统参数管理</h2>
<button data-modal-close="log-settings-modal" class="modal-close-btn">
<i class="fas fa-times text-lg"></i>
</button>
</div>
<!-- Form Body -->
<div class="modal-body flex-grow overflow-y-auto pr-4 -mr-4">
<div class="space-y-6">
<!-- 1. 系统日志级别 (修改为单行) -->
<div class="flex items-center justify-between">
<div>
<label for="log-level-select" class="flex items-center modal-label font-semibold">
<span>系统日志级别</span>
<i class="fas fa-question-circle tooltip-icon" data-tooltip-text="设置后台服务的日志输出详细程度。DEBUG最详细ERROR最精简。更改后实时生效。"></i>
</label>
<p class="modal-label-description">控制后台系统日志的输出级别。</p>
</div>
<select id="log-level-select" class="modal-input w-40">
<option value="DEBUG">DEBUG (调试)</option>
<option value="INFO">INFO (信息)</option>
<option value="WARNING">WARNING (警告)</option>
<option value="ERROR">ERROR (错误)</option>
</select>
</div>
<!-- 2. 请求日志自动清理 (修改为单行和新组件) -->
<div class="border-t border-border pt-6">
<div class="flex items-center justify-between">
<div>
<label for="log-cleanup-enable" class="modal-label flex-grow flex items-center font-semibold">
<span>开启请求日志自动清理</span>
<i class="fas fa-question-circle tooltip-icon" data-tooltip-text="启用后,系统将按计划自动删除旧的请求日志,以节省存储空间。"></i>
</label>
<p class="modal-label-description">定期清理超时的请求日志记录。</p>
</div>
<div class="relative inline-block w-10 mr-2 align-middle select-none transition duration-200 ease-in">
<input type="checkbox" name="log-cleanup-enable" id="log-cleanup-enable" class="toggle-checkbox absolute block w-6 h-6 rounded-full bg-white border-4 appearance-none cursor-pointer">
<label for="log-cleanup-enable" class="toggle-label block overflow-hidden h-6 rounded-full bg-gray-300 cursor-pointer"></label>
</div>
</div>
<!-- Collapsible settings for cleanup -->
<div id="log-cleanup-settings" class="mt-4 hidden">
<div class="flex items-center justify-between">
<label class="flex items-center modal-label">
<span>日志保留天数</span>
<i class="fas fa-question-circle tooltip-icon" data-tooltip-text="只保留最近 N 天的日志,早于此时间的日志将被删除。"></i>
</label>
<div id="retention-days-group" class="flex items-center space-x-2">
<button type="button" data-days="1" class="modal-btn modal-btn-secondary px-3 py-1 text-sm">1天</button>
<button type="button" data-days="7" class="modal-btn modal-btn-secondary px-3 py-1 text-sm">7天</button>
<button type="button" data-days="30" class="modal-btn modal-btn-secondary px-3 py-1 text-sm">30天</button>
<input type="number" id="log-cleanup-retention-days" class="modal-input w-28" placeholder="自定义天数">
</div>
</div>
</div>
</div>
<!-- [NEW] 每日清理执行时间 -->
<div class="flex items-center justify-between">
<label class="flex items-center modal-label">
<span>每日清理执行时间</span>
<i class="fas fa-question-circle tooltip-icon" data-tooltip-text="自动清理任务在每天的这个时间点执行基于服务器的UTC时间。"></i>
</label>
<input type="time" id="log-cleanup-exec-time" class="modal-input w-28">
</div>
<!-- 3. 日志备份 (待定) -->
<div class="border-t border-border pt-6 opacity-50">
<div class="flex items-center justify-between">
<div>
<label for="log-backup-enable" class="modal-label flex-grow flex items-center font-semibold">
<span>开启日志自动备份 (功能待定)</span>
<i class="fas fa-question-circle tooltip-icon" data-tooltip-text="此功能正在开发中。启用后,系统可将日志备份到指定位置。"></i>
</label>
<p class="modal-label-description">将系统和请求日志备份到指定路径。</p>
</div>
<div class="relative inline-block w-10 mr-2 align-middle select-none transition duration-200 ease-in">
<input type="checkbox" name="log-backup-enable" id="log-backup-enable" class="toggle-checkbox" disabled>
<label for="log-backup-enable" class="toggle-label"></label>
</div>
</div>
</div>
</div>
</div>
<!-- Footer -->
<div class="modal-footer shrink-0">
<button data-modal-close="log-settings-modal" class="modal-btn modal-btn-secondary">取消</button>
<button id="log-settings-save-btn" class="modal-btn modal-btn-primary">保存设置</button>
</div>
</div>
</div>
{% endblock modals %}
{% block page_scripts %}
{% endblock page_scripts %}