- tb_user 用户表、tb_log 日志表 - Flask-Login 认证(login/logout/权限装饰器) - 用户管理页(admin 专有):增删改查、改密、角色设置 - 操作日志页:分页查询、按用户/类型筛选 - 测试操作区指令自动记录日志 - 所有页面加 @login_required 保护 - 默认管理员 admin/admin123(首次启动自动创建)
93 lines
3.0 KiB
HTML
93 lines
3.0 KiB
HTML
{% extends "base.html" %}
|
|
{% block title %}操作日志 - EDC 工装管理系统{% endblock %}
|
|
|
|
{% block content %}
|
|
<h2>操作日志</h2>
|
|
|
|
<div class="search-bar">
|
|
<label>用户名:<input type="text" id="search-username" placeholder="筛选用户..."></label>
|
|
<label>操作类型:
|
|
<select id="search-action">
|
|
<option value="">全部</option>
|
|
<option value="login">登录</option>
|
|
<option value="logout">登出</option>
|
|
<option value="command">指令操作</option>
|
|
</select>
|
|
</label>
|
|
<button onclick="searchLogs(1)" class="btn-search">查询</button>
|
|
</div>
|
|
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>ID</th>
|
|
<th>用户</th>
|
|
<th>操作类型</th>
|
|
<th>对象</th>
|
|
<th>详情</th>
|
|
<th>结果</th>
|
|
<th>IP</th>
|
|
<th>时间</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="log-tbody"></tbody>
|
|
</table>
|
|
|
|
<div class="pagination" id="pagination"></div>
|
|
{% endblock %}
|
|
|
|
{% block scripts %}
|
|
<script>
|
|
let currentPage = 1, totalPages = 1;
|
|
|
|
async function searchLogs(page = 1) {
|
|
currentPage = page;
|
|
const username = document.getElementById("search-username").value;
|
|
const action_type = document.getElementById("search-action").value;
|
|
const params = new URLSearchParams({page, per_page: 30});
|
|
if (username) params.set("username", username);
|
|
if (action_type) params.set("action_type", action_type);
|
|
|
|
const resp = await fetch(`/logs/api/logs?${params}`);
|
|
const data = await resp.json();
|
|
renderTable(data.records);
|
|
totalPages = data.pages;
|
|
renderPagination();
|
|
}
|
|
|
|
function renderTable(records) {
|
|
const tbody = document.getElementById("log-tbody");
|
|
if (!records.length) {
|
|
tbody.innerHTML = '<tr><td colspan="8" style="text-align:center;color:#999;">暂无记录</td></tr>';
|
|
return;
|
|
}
|
|
tbody.innerHTML = records.map(r => `
|
|
<tr>
|
|
<td>${r.id}</td>
|
|
<td>${r.username || '-'}</td>
|
|
<td>${r.action_type}</td>
|
|
<td>${r.target || '-'}</td>
|
|
<td style="max-width:250px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;" title="${esc(r.detail)}">${r.detail || '-'}</td>
|
|
<td style="color:${r.result==='ok'?'#27ae60':'#e74c3c'}">${r.result}</td>
|
|
<td>${r.ip || '-'}</td>
|
|
<td>${r.create_time || '-'}</td>
|
|
</tr>
|
|
`).join("");
|
|
}
|
|
|
|
function renderPagination() {
|
|
const div = document.getElementById("pagination");
|
|
let html = `<button onclick="searchLogs(${currentPage-1})" ${currentPage<=1?'disabled':''}>上一页</button>`;
|
|
for (let i = 1; i <= totalPages; i++) {
|
|
html += `<button onclick="searchLogs(${i})" class="${i===currentPage?'active':''}">${i}</button>`;
|
|
}
|
|
html += `<button onclick="searchLogs(${currentPage+1})" ${currentPage>=totalPages?'disabled':''}>下一页</button>`;
|
|
div.innerHTML = html;
|
|
}
|
|
|
|
function esc(s) { return s.replace(/"/g, '"'); }
|
|
|
|
searchLogs(1);
|
|
</script>
|
|
{% endblock %}
|