316 lines
21 KiB
HTML
316 lines
21 KiB
HTML
{% 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="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 %} |