Часовой пояс и формат времени (24h/12h) перенесены из браузера в настройки приложения: валидация IANA-зоны, сид в db/init.sql + db/migration.sql, отдача в GET /api/public-settings, раздел #sec-datetime в настройках с живым превью. Границы суток в SQL переведены на tzDayStart/tzDayEnd + bindTz ($TZ$) — раньше $n::date по TIMESTAMPTZ считал дни в UTC (у контейнера TimeZone=UTC) и молча сдвигал выборку на день; хардкод Europe/Moscow вычищен, now() заменён на tzWall(). Новый public/js/datetime.js: три семейства хелперов (instant / чистая DATE-строка без Date() / чистая TIME-строка), подключён на всех страницах включая публичные share/report/index, initDateTime() встроен в checkAuth(). Прямые toLocale*/getFullYear/toISOString().slice(0,10) в public/ выпилены. Попутно: bindTz добавляет параметр только при наличии $TZ$ в SQL (иначе запрос виснет вечно без global error handler) — регрессия закрыта в api.smoketest.js; починены off-by-one месяца в report.js и группировка по дате в share.js.
61 lines
2.2 KiB
HTML
61 lines
2.2 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="ru">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
<title>Аудит — Админ-панель</title>
|
|
<link rel="stylesheet" href="admin.css">
|
|
</head>
|
|
<body data-page="audit">
|
|
<div class="layout">
|
|
<div class="sidebar" id="sidebar"></div>
|
|
<div class="main">
|
|
<div class="page-head">
|
|
<h2>Аудит-журнал</h2>
|
|
<p class="page-sub">Действия администратора</p>
|
|
</div>
|
|
|
|
<div class="actions-row">
|
|
<select id="auditActionFilter" class="settings-input" style="max-width:280px">
|
|
<option value="">Все действия</option>
|
|
</select>
|
|
<input type="search" id="auditFilter" class="settings-input" placeholder="Фильтр по действию..." style="max-width:300px">
|
|
<button class="btn-link" id="auditRefreshBtn" type="button" title="Обновить">Обновить</button>
|
|
<span class="hint" id="auditCount"></span>
|
|
</div>
|
|
|
|
<div class="audit-wrap" style="margin-top:14px">
|
|
<table class="audit-table" id="auditTable">
|
|
<thead>
|
|
<tr>
|
|
<th>Время</th>
|
|
<th>Кто</th>
|
|
<th>Действие</th>
|
|
<th>Детали</th>
|
|
<th>IP</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody></tbody>
|
|
</table>
|
|
<div class="empty" id="auditEmpty" style="display:none">Записей пока нет.</div>
|
|
</div>
|
|
<div class="pager" id="auditPager"></div>
|
|
</div>
|
|
</div>
|
|
<div class="modal-overlay" id="auditDetailsModal">
|
|
<div class="edit-modal" style="max-width:820px">
|
|
<h3 id="auditDetailsTitle">Детали действия</h3>
|
|
<div class="audit-details-head" id="auditDetailsHead"></div>
|
|
<div class="audit-details-body" id="auditDetailsBody"></div>
|
|
<div class="card-foot" style="justify-content:flex-end;gap:8px">
|
|
<button type="button" class="btn-primary ghost" id="auditDetailsCloseBtn">Закрыть</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="toast" id="toast"></div>
|
|
<script src="vendor/lucide.min.js"></script>
|
|
<script src="js/datetime.js"></script>
|
|
<script src="admin.js"></script>
|
|
<script src="js/audit.js"></script>
|
|
</body>
|
|
</html> |