feat(admin): 添加系统日志功能
## 新功能 1. **系统日志数据库** - 新增 system_logs 表 - 支持日志级别:debug/info/warn/error - 支持日志分类:auth/user/file/share/system/security - 记录用户ID、用户名、IP地址、User-Agent 2. **日志记录** - 用户注册成功/失败 - 用户登录成功/失败(密码错误) - 系统操作(日志清理等) 3. **管理员API** - GET /api/admin/logs - 查询日志(支持分页和筛选) - GET /api/admin/logs/stats - 获取日志统计 - POST /api/admin/logs/cleanup - 清理旧日志 4. **前端界面** - 日志列表展示(时间、级别、分类、内容、用户、IP) - 筛选功能(级别、分类、关键词搜索) - 分页导航 - 清理旧日志功能 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1874,6 +1874,118 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 系统日志 -->
|
||||
<div class="card" style="margin-bottom: 30px;">
|
||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px;">
|
||||
<h3 style="margin: 0;">
|
||||
<i class="fas fa-clipboard-list"></i> 系统日志
|
||||
</h3>
|
||||
<div style="display: flex; gap: 10px;">
|
||||
<button class="btn btn-secondary" @click="cleanupLogs" title="清理90天前的日志">
|
||||
<i class="fas fa-trash"></i> 清理旧日志
|
||||
</button>
|
||||
<button class="btn btn-primary" @click="loadSystemLogs(1)" :disabled="systemLogs.loading">
|
||||
<i class="fas" :class="systemLogs.loading ? 'fa-spinner fa-spin' : 'fa-sync'"></i>
|
||||
刷新
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 筛选器 -->
|
||||
<div style="display: flex; gap: 12px; flex-wrap: wrap; margin-bottom: 15px; padding: 15px; background: #f8f9fa; border-radius: 8px;">
|
||||
<div style="display: flex; align-items: center; gap: 8px;">
|
||||
<label style="font-size: 13px; color: #666;">级别:</label>
|
||||
<select v-model="systemLogs.filters.level" @change="filterLogs" style="padding: 6px 10px; border: 1px solid #ddd; border-radius: 4px;">
|
||||
<option value="">全部</option>
|
||||
<option value="info">信息</option>
|
||||
<option value="warn">警告</option>
|
||||
<option value="error">错误</option>
|
||||
</select>
|
||||
</div>
|
||||
<div style="display: flex; align-items: center; gap: 8px;">
|
||||
<label style="font-size: 13px; color: #666;">分类:</label>
|
||||
<select v-model="systemLogs.filters.category" @change="filterLogs" style="padding: 6px 10px; border: 1px solid #ddd; border-radius: 4px;">
|
||||
<option value="">全部</option>
|
||||
<option value="auth">认证</option>
|
||||
<option value="user">用户</option>
|
||||
<option value="file">文件</option>
|
||||
<option value="share">分享</option>
|
||||
<option value="system">系统</option>
|
||||
<option value="security">安全</option>
|
||||
</select>
|
||||
</div>
|
||||
<div style="display: flex; align-items: center; gap: 8px; flex: 1; min-width: 200px;">
|
||||
<label style="font-size: 13px; color: #666;">搜索:</label>
|
||||
<input type="text" v-model="systemLogs.filters.keyword" @keyup.enter="filterLogs"
|
||||
placeholder="搜索日志内容..." style="flex: 1; padding: 6px 10px; border: 1px solid #ddd; border-radius: 4px;">
|
||||
</div>
|
||||
<button class="btn btn-secondary" @click="clearLogFilters" style="padding: 6px 12px;">
|
||||
<i class="fas fa-times"></i> 清除筛选
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- 日志统计 -->
|
||||
<div v-if="systemLogs.total > 0" style="margin-bottom: 15px; font-size: 13px; color: #666;">
|
||||
共 {{ systemLogs.total }} 条日志,第 {{ systemLogs.page }}/{{ systemLogs.totalPages }} 页
|
||||
</div>
|
||||
|
||||
<!-- 日志列表 -->
|
||||
<div v-if="systemLogs.logs.length > 0" style="max-height: 500px; overflow-y: auto;">
|
||||
<div v-for="log in systemLogs.logs" :key="log.id"
|
||||
style="display: flex; gap: 12px; padding: 12px; border-bottom: 1px solid #eee; align-items: flex-start;">
|
||||
<!-- 时间 -->
|
||||
<div style="width: 140px; flex-shrink: 0; font-size: 12px; color: #888;">
|
||||
{{ formatLogTime(log.created_at) }}
|
||||
</div>
|
||||
<!-- 级别标签 -->
|
||||
<div style="width: 50px; flex-shrink: 0;">
|
||||
<span :style="getLogLevelColor(log.level)" style="padding: 2px 8px; border-radius: 4px; font-size: 11px;">
|
||||
{{ getLogLevelText(log.level) }}
|
||||
</span>
|
||||
</div>
|
||||
<!-- 分类图标 -->
|
||||
<div style="width: 70px; flex-shrink: 0; display: flex; align-items: center; gap: 4px; font-size: 12px; color: #666;">
|
||||
<i class="fas" :class="getLogCategoryIcon(log.category)"></i>
|
||||
{{ getLogCategoryText(log.category) }}
|
||||
</div>
|
||||
<!-- 内容 -->
|
||||
<div style="flex: 1; min-width: 0;">
|
||||
<div style="font-weight: 500; margin-bottom: 4px;">{{ log.action }}</div>
|
||||
<div style="font-size: 13px; color: #555;">{{ log.message }}</div>
|
||||
<div v-if="log.username || log.ip_address" style="font-size: 11px; color: #888; margin-top: 4px;">
|
||||
<span v-if="log.username"><i class="fas fa-user"></i> {{ log.username }}</span>
|
||||
<span v-if="log.ip_address" style="margin-left: 10px;"><i class="fas fa-globe"></i> {{ log.ip_address }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 空状态 -->
|
||||
<div v-else-if="!systemLogs.loading" style="text-align: center; padding: 40px; color: #888;">
|
||||
<i class="fas fa-clipboard" style="font-size: 48px; margin-bottom: 15px;"></i>
|
||||
<p>暂无日志记录</p>
|
||||
</div>
|
||||
|
||||
<!-- 加载中 -->
|
||||
<div v-if="systemLogs.loading" style="text-align: center; padding: 40px; color: #888;">
|
||||
<i class="fas fa-spinner fa-spin" style="font-size: 24px;"></i>
|
||||
<p>加载中...</p>
|
||||
</div>
|
||||
|
||||
<!-- 分页 -->
|
||||
<div v-if="systemLogs.totalPages > 1" style="display: flex; justify-content: center; gap: 8px; margin-top: 15px;">
|
||||
<button class="btn btn-secondary" @click="loadSystemLogs(systemLogs.page - 1)" :disabled="systemLogs.page <= 1" style="padding: 6px 12px;">
|
||||
<i class="fas fa-chevron-left"></i> 上一页
|
||||
</button>
|
||||
<span style="display: flex; align-items: center; padding: 0 15px; color: #666;">
|
||||
{{ systemLogs.page }} / {{ systemLogs.totalPages }}
|
||||
</span>
|
||||
<button class="btn btn-secondary" @click="loadSystemLogs(systemLogs.page + 1)" :disabled="systemLogs.page >= systemLogs.totalPages" style="padding: 6px 12px;">
|
||||
下一页 <i class="fas fa-chevron-right"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3 style="margin-bottom: 20px;">用户管理</h3>
|
||||
<div style="overflow-x: auto;">
|
||||
<table style="width: 100%; border-collapse: collapse; table-layout: fixed; min-width: 900px;">
|
||||
|
||||
Reference in New Issue
Block a user