2025-05-12 02:42:27 +08:00

254 lines
12 KiB
HTML

{% extends 'base.html' %}
{% block title %}系统日志管理{% endblock %}
{% block head %}
<link rel="stylesheet" href="{{ url_for('static', filename='css/log-list.css') }}">
<link href="https://fonts.googleapis.com/css2?family=Dancing+Script&family=Montserrat:wght@300;400;500&display=swap" rel="stylesheet">
{% endblock %}
{% block content %}
<div class="content-container">
<div class="content-header">
<h1><i class="fas fa-history sparkle"></i> 系统日志管理</h1>
<div class="actions">
<button id="btnExport" class="btn btn-blossom">
<i class="fas fa-file-export"></i> 导出日志
</button>
<button id="btnClear" class="btn btn-danger-soft">
<i class="fas fa-trash"></i> 清除日志
</button>
</div>
</div>
<div class="filter-panel">
<div class="filter-panel-header">
<span class="filter-title">日志筛选</span>
<div class="snowflake-divider">
<span></span><span></span><span></span>
</div>
</div>
<form method="get" action="{{ url_for('log.log_list') }}">
<div class="filter-row">
<div class="filter-item">
<label for="user_id">用户</label>
<select name="user_id" id="user_id" class="elegant-select">
<option value="">全部用户</option>
{% for user in users %}
<option value="{{ user.id }}" {% if filters.user_id == user.id %}selected{% endif %}>
{{ user.username }}
</option>
{% endfor %}
</select>
</div>
<div class="filter-item">
<label for="action">操作类型</label>
<select name="action" id="action" class="elegant-select">
<option value="">全部操作</option>
{% for action_type, count in action_types %}
<option value="{{ action_type }}" {% if filters.action == action_type %}selected{% endif %}>
{{ action_type }} ({{ count }})
</option>
{% endfor %}
</select>
</div>
<div class="filter-item">
<label for="target_type">目标类型</label>
<select name="target_type" id="target_type" class="elegant-select">
<option value="">全部类型</option>
{% for target_type, count in target_types %}
<option value="{{ target_type }}" {% if filters.target_type == target_type %}selected{% endif %}>
{{ target_type }} ({{ count }})
</option>
{% endfor %}
</select>
</div>
<div class="filter-item">
<label for="date_range">时间范围</label>
<select name="date_range" id="date_range" class="elegant-select">
<option value="1" {% if filters.date_range == '1' %}selected{% endif %}>最近1天</option>
<option value="7" {% if filters.date_range == '7' %}selected{% endif %}>最近7天</option>
<option value="30" {% if filters.date_range == '30' %}selected{% endif %}>最近30天</option>
<option value="custom" {% if filters.date_range == 'custom' %}selected{% endif %}>自定义</option>
</select>
</div>
</div>
<div class="filter-row date-range-inputs" {% if filters.date_range != 'custom' %}style="display:none"{% endif %}>
<div class="filter-item">
<label for="start_date">开始日期</label>
<input type="date" name="start_date" id="start_date" value="{{ filters.start_date }}" class="elegant-input">
</div>
<div class="filter-item">
<label for="end_date">结束日期</label>
<input type="date" name="end_date" id="end_date" value="{{ filters.end_date }}" class="elegant-input">
</div>
</div>
<div class="filter-actions">
<button type="submit" class="btn btn-primary-soft">应用筛选</button>
<a href="{{ url_for('log.log_list') }}" class="btn btn-secondary-soft">重置</a>
</div>
</form>
</div>
<div class="card glass-card">
<div class="card-body">
<div class="table-container">
<table class="table elegant-table">
<thead>
<tr>
<th>#</th>
<th>用户</th>
<th>操作</th>
<th>目标类型</th>
<th>目标ID</th>
<th>IP地址</th>
<th>描述</th>
<th>时间</th>
</tr>
</thead>
<tbody>
{% for log in pagination.items %}
<tr class="fade-in-row">
<td>{{ log.id }}</td>
<td>
{% if log.user %}
<span class="user-badge">{{ log.user.username }}</span>
{% else %}
<span class="text-muted">未登录</span>
{% endif %}
</td>
<td>{{ log.action }}</td>
<td>{{ log.target_type }}</td>
<td>{{ log.target_id }}</td>
<td>{{ log.ip_address }}</td>
<td>{{ log.description }}</td>
<td>{{ log.created_at.strftime('%Y-%m-%d %H:%M:%S') }}</td>
</tr>
{% else %}
<tr>
<td colspan="8" class="text-center empty-message">
<div class="empty-container">
<i class="fas fa-search"></i>
<p>没有找到符合条件的日志记录</p>
</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<!-- 分页部分 -->
<div class="pagination-wrapper">
<div class="pagination-container">
{% if pagination.has_prev %}
<a href="{{ url_for('log.log_list', page=pagination.prev_num, user_id=filters.user_id, action=filters.action, target_type=filters.target_type, date_range=filters.date_range, start_date=filters.start_date, end_date=filters.end_date) }}" class="btn btn-sm btn-outline-primary page-btn"><i class="fas fa-chevron-left"></i> 上一页</a>
{% endif %}
<span class="page-info">
第 {{ pagination.page }} 页,共 {{ pagination.pages }} 页,总计 {{ pagination.total }} 条记录
</span>
{% if pagination.has_next %}
<a href="{{ url_for('log.log_list', page=pagination.next_num, user_id=filters.user_id, action=filters.action, target_type=filters.target_type, date_range=filters.date_range, start_date=filters.start_date, end_date=filters.end_date) }}" class="btn btn-sm btn-outline-primary page-btn">下一页 <i class="fas fa-chevron-right"></i></a>
{% endif %}
</div>
</div>
</div>
</div>
</div>
<!-- 导出日志模态框 -->
<div class="modal fade" id="exportLogModal" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-elegant" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title"><i class="fas fa-file-export"></i> 导出日志</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<p class="modal-message">请选择导出格式:</p>
<div class="form-group">
<select id="exportFormat" class="form-control elegant-select">
<option value="csv">CSV 格式</option>
<option value="excel">Excel 格式</option>
</select>
</div>
<div class="alert alert-info elegant-alert">
<i class="fas fa-info-circle"></i> 将导出当前筛选条件下的所有日志记录。
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary-soft" data-dismiss="modal">取消</button>
<button type="button" id="confirmExport" class="btn btn-primary-soft">确认导出</button>
</div>
</div>
</div>
</div>
<!-- 清除日志确认框 -->
<div class="modal fade" id="clearLogModal" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-elegant" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title"><i class="fas fa-trash-alt"></i> 清除日志确认</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<p class="modal-message">请选择要清除的日志范围:</p>
<div class="form-group">
<select id="clearDays" class="form-control elegant-select">
<option value="0">清除全部日志</option>
<option value="30">清除30天前的日志</option>
<option value="90">清除90天前的日志</option>
<option value="180">清除半年前的日志</option>
<option value="365">清除一年前的日志</option>
</select>
</div>
<div class="alert alert-warning elegant-alert">
<i class="fas fa-exclamation-triangle"></i> 警告:此操作不可恢复!
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary-soft" data-dismiss="modal">取消</button>
<button type="button" id="confirmClear" class="btn btn-danger-soft">确认清除</button>
</div>
</div>
</div>
</div>
{% endblock %}
{% block scripts %}
<script src="{{ url_for('static', filename='js/log-list.js') }}"></script>
<script>
// 添加雪花动画效果
document.addEventListener('DOMContentLoaded', function() {
// 为表格行添加渐入效果
const rows = document.querySelectorAll('.fade-in-row');
rows.forEach((row, index) => {
row.style.animationDelay = `${index * 0.05}s`;
});
// 为按钮添加悬停效果
const buttons = document.querySelectorAll('.btn');
buttons.forEach(btn => {
btn.addEventListener('mouseover', function() {
this.classList.add('btn-glow');
});
btn.addEventListener('mouseout', function() {
this.classList.remove('btn-glow');
});
});
});
</script>
{% endblock %}