123 lines
6.8 KiB
Plaintext
123 lines
6.8 KiB
Plaintext
@page "/admin/system/audit"
|
|
@layout AdminLayout
|
|
@inherits AdminBase
|
|
|
|
@*
|
|
EN: Audit log — action log table with timestamp, user, action, resource, status. Search + filter by action type, date range, user.
|
|
VI: Nhật ký hệ thống — bảng log thao tác với thời gian, người dùng, hành động, tài nguyên, trạng thái. Tìm kiếm + lọc.
|
|
Design: pencil-design/src/pages/tPOS/admin/audit-log.pen
|
|
*@
|
|
|
|
<PageTitle>Nhật ký hệ thống — GoodGo Admin</PageTitle>
|
|
|
|
@* ═══ TOP BAR ═══ *@
|
|
<div class="admin-topbar">
|
|
<div class="admin-topbar__left">
|
|
<h1 class="admin-topbar__title">Nhật ký hệ thống</h1>
|
|
<p class="admin-topbar__subtitle">Lịch sử thao tác & sự kiện hệ thống</p>
|
|
</div>
|
|
<div class="admin-topbar__right">
|
|
<div class="admin-search" style="width:220px;">
|
|
<i data-lucide="search"></i>
|
|
<input type="text" placeholder="Tìm trong log..." @bind="SearchQuery" />
|
|
</div>
|
|
<button class="admin-btn-secondary">
|
|
<i data-lucide="filter"></i>
|
|
<span>Bộ lọc</span>
|
|
</button>
|
|
<button class="admin-btn-secondary">
|
|
<i data-lucide="download"></i>
|
|
<span>Xuất log</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
@* ═══ TABS ═══ *@
|
|
<div class="admin-tabs">
|
|
<button class="admin-tab @(_activeTab == "all" ? "admin-tab--active" : "")" @onclick="@(() => _activeTab = "all")">
|
|
Tất cả <span class="admin-tab__badge admin-tab__badge--active">@_logs.Count</span>
|
|
</button>
|
|
<button class="admin-tab @(_activeTab == "auth" ? "admin-tab--active" : "")" @onclick="@(() => _activeTab = "auth")">
|
|
Xác thực <span class="admin-tab__badge">@_logs.Count(l => l.Category == "auth")</span>
|
|
</button>
|
|
<button class="admin-tab @(_activeTab == "config" ? "admin-tab--active" : "")" @onclick="@(() => _activeTab = "config")">
|
|
Cấu hình <span class="admin-tab__badge">@_logs.Count(l => l.Category == "config")</span>
|
|
</button>
|
|
<button class="admin-tab @(_activeTab == "data" ? "admin-tab--active" : "")" @onclick="@(() => _activeTab = "data")">
|
|
Dữ liệu <span class="admin-tab__badge">@_logs.Count(l => l.Category == "data")</span>
|
|
</button>
|
|
</div>
|
|
|
|
@* ═══ LOG TABLE ═══ *@
|
|
<div class="admin-content" style="display:flex;flex-direction:column;gap:0;">
|
|
<div class="admin-panel" style="flex:1;">
|
|
<div class="admin-panel__body" style="padding:0;">
|
|
<table class="admin-table">
|
|
<thead>
|
|
<tr>
|
|
<th>Thời gian</th>
|
|
<th>Người dùng</th>
|
|
<th>Hành động</th>
|
|
<th>Tài nguyên</th>
|
|
<th>IP</th>
|
|
<th>Trạng thái</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@foreach (var log in FilteredLogs)
|
|
{
|
|
<tr>
|
|
<td style="font-size:12px;color:var(--admin-text-tertiary);white-space:nowrap;">@log.Timestamp</td>
|
|
<td>
|
|
<div style="display:flex;align-items:center;gap:8px;">
|
|
<div class="admin-user-avatar" style="width:28px;height:28px;font-size:10px;background-color:@log.AvatarColor;">@log.Initials</div>
|
|
<span style="font-weight:500;">@log.User</span>
|
|
</div>
|
|
</td>
|
|
<td>
|
|
<div style="display:flex;align-items:center;gap:6px;">
|
|
<i data-lucide="@log.ActionIcon" style="width:14px;height:14px;color:@log.ActionColor;"></i>
|
|
<span>@log.Action</span>
|
|
</div>
|
|
</td>
|
|
<td style="color:var(--admin-text-secondary);">@log.Resource</td>
|
|
<td style="font-size:12px;color:var(--admin-text-tertiary);font-family:monospace;">@log.IP</td>
|
|
<td>
|
|
<div class="admin-status-badge @(log.Status == "success" ? "admin-status-badge--online" : "admin-status-badge--offline")">
|
|
<span class="admin-status-badge__dot"></span>
|
|
@(log.Status == "success" ? "Thành công" : "Thất bại")
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
@code {
|
|
private string _activeTab = "all";
|
|
|
|
private List<LogEntry> FilteredLogs => _activeTab == "all"
|
|
? _logs
|
|
: _logs.Where(l => l.Category == _activeTab).ToList();
|
|
|
|
private record LogEntry(string Timestamp, string User, string Initials, string AvatarColor, string Action,
|
|
string ActionIcon, string ActionColor, string Resource, string IP, string Status, string Category);
|
|
|
|
private readonly List<LogEntry> _logs = new()
|
|
{
|
|
new("12/02/2026 14:32:05", "Trần Minh Đức", "TM", "#FF5C00", "Đăng nhập", "log-in", "#22C55E", "Phiên làm việc", "192.168.1.45", "success", "auth"),
|
|
new("12/02/2026 14:28:11", "Admin System", "AS", "#8B5CF6", "Cập nhật giá", "edit", "#3B82F6", "Sản phẩm #142", "10.0.0.1", "success", "data"),
|
|
new("12/02/2026 14:15:30", "Lê Thị Thảo", "LT", "#3B82F6", "Tạo đơn hàng", "plus-circle", "#22C55E", "Đơn #2848", "192.168.1.50", "success", "data"),
|
|
new("12/02/2026 13:55:22", "Phạm Văn An", "PA", "#22C55E", "Thay đổi quyền", "shield", "#F59E0B", "Role: Barista", "192.168.1.12", "success", "config"),
|
|
new("12/02/2026 13:42:08", "Nguyễn Hà My", "NH", "#EC4899", "Đăng nhập thất bại", "log-in", "#EF4444", "Phiên làm việc", "192.168.1.88", "failed", "auth"),
|
|
new("12/02/2026 13:30:00", "Admin System", "AS", "#8B5CF6", "Backup dữ liệu", "database", "#3B82F6", "DB chính", "10.0.0.1", "success", "config"),
|
|
new("12/02/2026 12:18:45", "Võ Đình Khoa", "VK", "#F59E0B", "Nhập kho", "package", "#22C55E", "Kho Coffee Q1", "192.168.1.33", "success", "data"),
|
|
new("12/02/2026 11:55:12", "Trần Minh Đức", "TM", "#FF5C00", "Cập nhật cài đặt", "settings", "#F59E0B", "Cửa hàng Q1", "192.168.1.45", "success", "config"),
|
|
new("12/02/2026 10:30:00", "Lê Thị Thảo", "LT", "#3B82F6", "Hủy đơn hàng", "x-circle", "#EF4444", "Đơn #2845", "192.168.1.50", "success", "data"),
|
|
new("12/02/2026 09:15:33", "Phạm Văn An", "PA", "#22C55E", "Đăng nhập", "log-in", "#22C55E", "Phiên làm việc", "192.168.1.12", "success", "auth"),
|
|
};
|
|
}
|