2025-07-09 05:22:28 +08:00

246 lines
11 KiB
HTML

{% extends "admin/base.html" %}
{% block title %}操作日志 - 太白购物商城管理后台{% endblock %}
{% block page_title %}操作日志{% endblock %}
{% block page_description %}查看系统操作日志,监控用户和管理员行为{% endblock %}
{% block extra_css %}
<link href="{{ url_for('static', filename='css/admin_logs.css') }}" rel="stylesheet">
{% endblock %}
{% block content %}
<div class="admin-logs">
<!-- 筛选条件 -->
<div class="card mb-4">
<div class="card-body">
<form method="GET" class="row g-3">
<div class="col-md-3">
<label for="user_type" class="form-label">用户类型</label>
<select class="form-select" id="user_type" name="user_type">
<option value="">全部类型</option>
<option value="1" {% if user_type == '1' %}selected{% endif %}>普通用户</option>
<option value="2" {% if user_type == '2' %}selected{% endif %}>管理员</option>
</select>
</div>
<div class="col-md-4">
<label for="action" class="form-label">操作类型</label>
<input type="text" class="form-control" id="action" name="action"
value="{{ action }}" placeholder="搜索操作类型">
</div>
<div class="col-md-2">
<label class="form-label">&nbsp;</label>
<div class="d-flex gap-2">
<button type="submit" class="btn btn-primary">
<i class="bi bi-search"></i> 搜索
</button>
<a href="{{ url_for('admin.logs') }}" class="btn btn-outline-secondary">
<i class="bi bi-arrow-clockwise"></i> 重置
</a>
</div>
</div>
</form>
</div>
</div>
<!-- 日志统计 -->
<div class="row mb-4">
<div class="col-md-3">
<div class="card stats-card">
<div class="card-body">
<div class="d-flex align-items-center">
<div class="flex-grow-1">
<h5 class="card-title">{{ logs.total }}</h5>
<p class="card-text">总日志数</p>
</div>
<div class="icon-wrapper primary">
<i class="bi bi-journal-text"></i>
</div>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card stats-card">
<div class="card-body">
<div class="d-flex align-items-center">
<div class="flex-grow-1">
<h5 class="card-title">{{ logs.items | selectattr('user_type', 'equalto', 1) | list | length }}</h5>
<p class="card-text">用户操作</p>
</div>
<div class="icon-wrapper info">
<i class="bi bi-person"></i>
</div>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card stats-card">
<div class="card-body">
<div class="d-flex align-items-center">
<div class="flex-grow-1">
<h5 class="card-title">{{ logs.items | selectattr('user_type', 'equalto', 2) | list | length }}</h5>
<p class="card-text">管理员操作</p>
</div>
<div class="icon-wrapper warning">
<i class="bi bi-shield-check"></i>
</div>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card stats-card">
<div class="card-body">
<div class="d-flex align-items-center">
<div class="flex-grow-1">
<h5 class="card-title">{{ today_logs_count }}</h5>
<p class="card-text">今日操作</p>
</div>
<div class="icon-wrapper success">
<i class="bi bi-clock"></i>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 日志列表 -->
<div class="card">
<div class="card-header bg-white">
<h5 class="mb-0">
<i class="bi bi-journal-text"></i>
操作日志
<small class="text-muted ms-2">共 {{ logs.total }} 条记录</small>
</h5>
</div>
<div class="table-responsive">
<table class="table table-hover mb-0">
<thead class="table-light">
<tr>
<th width="15%">时间</th>
<th width="10%">操作者</th>
<th width="15%">操作类型</th>
<th width="20%">操作内容</th>
<th width="15%">IP地址</th>
<th width="25%">用户代理</th>
</tr>
</thead>
<tbody>
{% if logs.items %}
{% for log in logs.items %}
<tr>
<td>
<div>{{ log.created_at.strftime('%Y-%m-%d') if log.created_at else '-' }}</div>
<small class="text-muted">{{ log.created_at.strftime('%H:%M:%S') if log.created_at else '' }}</small>
</td>
<td>
<div class="d-flex align-items-center">
<span class="badge bg-{{ 'warning' if log.user_type == 2 else 'info' }} me-2">
{{ '管理员' if log.user_type == 2 else '用户' }}
</span>
<span class="fw-bold">#{{ log.user_id or '-' }}</span>
</div>
</td>
<td>
<span class="operation-action">{{ log.action }}</span>
</td>
<td>
<div>
{% if log.resource_type %}
<span class="resource-type">{{ log.resource_type }}</span>
{% if log.resource_id %}
<span class="resource-id">#{{ log.resource_id }}</span>
{% endif %}
{% else %}
<span class="text-muted">-</span>
{% endif %}
</div>
</td>
<td>
<code>{{ log.ip_address or '-' }}</code>
</td>
<td>
<div class="user-agent-wrapper">
{% if log.user_agent %}
<span class="user-agent" title="{{ log.user_agent }}">
{{ log.user_agent[:50] }}{% if log.user_agent|length > 50 %}...{% endif %}
</span>
{% else %}
<span class="text-muted">-</span>
{% endif %}
</div>
</td>
</tr>
{% endfor %}
{% else %}
<tr>
<td colspan="6" class="text-center py-4">
<div class="empty-state">
<i class="bi bi-journal-x"></i>
<div>暂无操作日志</div>
{% if user_type or action %}
<small class="text-muted">尝试调整筛选条件</small>
{% endif %}
</div>
</td>
</tr>
{% endif %}
</tbody>
</table>
</div>
<!-- 分页 -->
{% if logs.pages > 1 %}
<div class="card-footer bg-white">
<nav aria-label="操作日志分页">
<ul class="pagination justify-content-center mb-0">
{% if logs.has_prev %}
<li class="page-item">
<a class="page-link" href="{{ url_for('admin.logs', page=logs.prev_num, user_type=user_type, action=action) }}">
<i class="bi bi-chevron-left"></i>
</a>
</li>
{% endif %}
{% for page_num in logs.iter_pages(left_edge=1, right_edge=1, left_current=1, right_current=2) %}
{% if page_num %}
{% if page_num != logs.page %}
<li class="page-item">
<a class="page-link" href="{{ url_for('admin.logs', page=page_num, user_type=user_type, action=action) }}">
{{ page_num }}
</a>
</li>
{% else %}
<li class="page-item active">
<span class="page-link">{{ page_num }}</span>
</li>
{% endif %}
{% else %}
<li class="page-item disabled">
<span class="page-link"></span>
</li>
{% endif %}
{% endfor %}
{% if logs.has_next %}
<li class="page-item">
<a class="page-link" href="{{ url_for('admin.logs', page=logs.next_num, user_type=user_type, action=action) }}">
<i class="bi bi-chevron-right"></i>
</a>
</li>
{% endif %}
</ul>
</nav>
</div>
{% endif %}
</div>
</div>
{% endblock %}
{% block extra_js %}
<script src="{{ url_for('static', filename='js/admin_logs.js') }}"></script>
{% endblock %}