第一次提交
This commit is contained in:
280
app/web/templates/log/list.html
Normal file
280
app/web/templates/log/list.html
Normal file
@@ -0,0 +1,280 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}操作日志{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">操作日志</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<!-- 筛选表单 -->
|
||||
<form id="logFilterForm" class="mb-3">
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
<label for="action" class="form-label">操作类型</label>
|
||||
<select class="form-select" id="action" name="action">
|
||||
<option value="">全部</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<label for="target_type" class="form-label">目标类型</label>
|
||||
<select class="form-select" id="target_type" name="target_type">
|
||||
<option value="">全部</option>
|
||||
<option value="ADMIN">管理员</option>
|
||||
<option value="PRODUCT">产品</option>
|
||||
<option value="VERSION">版本</option>
|
||||
<option value="LICENSE">卡密</option>
|
||||
<option value="DEVICE">设备</option>
|
||||
<option value="TICKET">工单</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<label for="start_date" class="form-label">开始日期</label>
|
||||
<input type="date" class="form-control" id="start_date" name="start_date">
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<label for="end_date" class="form-label">结束日期</label>
|
||||
<input type="date" class="form-control" id="end_date" name="end_date">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-2">
|
||||
<div class="col-md-12">
|
||||
<button type="submit" class="btn btn-primary">筛选</button>
|
||||
<button type="button" class="btn btn-secondary" id="resetFilter">重置</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<!-- 日志表格 -->
|
||||
<div class="table-responsive">
|
||||
<table class="table table-bordered table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>操作员</th>
|
||||
<th>操作类型</th>
|
||||
<th>目标类型</th>
|
||||
<th>目标ID</th>
|
||||
<th>详情</th>
|
||||
<th>IP地址</th>
|
||||
<th>时间</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="logTableBody">
|
||||
<!-- 日志数据将通过AJAX加载 -->
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- 分页 -->
|
||||
<div id="pagination" class="d-flex justify-content-center">
|
||||
<!-- 分页控件将通过JavaScript生成 -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 系统日志模态框 -->
|
||||
<div class="modal fade" id="systemLogModal" tabindex="-1" aria-labelledby="systemLogModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-xl">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="systemLogModalLabel">系统日志</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<pre id="systemLogContent" style="max-height: 500px; overflow-y: auto;"></pre>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">关闭</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
<script>
|
||||
// 全局变量
|
||||
let currentPage = 1;
|
||||
const perPage = 20;
|
||||
|
||||
// 页面加载完成后初始化
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// 加载操作类型列表
|
||||
loadActionList();
|
||||
|
||||
// 加载日志数据
|
||||
loadLogs();
|
||||
|
||||
// 绑定筛选表单事件
|
||||
document.getElementById('logFilterForm').addEventListener('submit', function(e) {
|
||||
e.preventDefault();
|
||||
currentPage = 1;
|
||||
loadLogs();
|
||||
});
|
||||
|
||||
// 绑定重置按钮事件
|
||||
document.getElementById('resetFilter').addEventListener('click', function() {
|
||||
document.getElementById('logFilterForm').reset();
|
||||
currentPage = 1;
|
||||
loadLogs();
|
||||
});
|
||||
});
|
||||
|
||||
// 加载操作类型列表
|
||||
function loadActionList() {
|
||||
apiRequest('/api/v1/logs/actions')
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
const actionSelect = document.getElementById('action');
|
||||
data.data.actions.forEach(action => {
|
||||
const option = document.createElement('option');
|
||||
option.value = action;
|
||||
option.textContent = action;
|
||||
actionSelect.appendChild(option);
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('加载操作类型列表失败:', error);
|
||||
});
|
||||
}
|
||||
|
||||
// 加载日志数据
|
||||
function loadLogs(page = 1) {
|
||||
currentPage = page;
|
||||
|
||||
// 构建查询参数
|
||||
const params = new URLSearchParams();
|
||||
params.append('page', currentPage);
|
||||
params.append('per_page', perPage);
|
||||
|
||||
// 添加筛选条件
|
||||
const action = document.getElementById('action').value;
|
||||
const target_type = document.getElementById('target_type').value;
|
||||
const start_date = document.getElementById('start_date').value;
|
||||
const end_date = document.getElementById('end_date').value;
|
||||
|
||||
if (action) params.append('action', action);
|
||||
if (target_type) params.append('target_type', target_type);
|
||||
if (start_date) params.append('start_date', start_date);
|
||||
if (end_date) params.append('end_date', end_date);
|
||||
|
||||
// 发送请求
|
||||
apiRequest(`/api/v1/logs?${params.toString()}`)
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
renderLogs(data.data.logs);
|
||||
renderPagination(data.data.pagination);
|
||||
} else {
|
||||
alert('加载日志失败: ' + data.message);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('加载日志失败:', error);
|
||||
alert('加载日志失败,请稍后重试');
|
||||
});
|
||||
}
|
||||
|
||||
// 渲染日志数据
|
||||
function renderLogs(logs) {
|
||||
const tbody = document.getElementById('logTableBody');
|
||||
tbody.innerHTML = '';
|
||||
|
||||
if (logs.length === 0) {
|
||||
const tr = document.createElement('tr');
|
||||
tr.innerHTML = '<td colspan="8" class="text-center">暂无日志数据</td>';
|
||||
tbody.appendChild(tr);
|
||||
return;
|
||||
}
|
||||
|
||||
logs.forEach(log => {
|
||||
const tr = document.createElement('tr');
|
||||
tr.innerHTML = `
|
||||
<td>${log.log_id}</td>
|
||||
<td>${log.admin_username || '系统'}</td>
|
||||
<td>${log.action}</td>
|
||||
<td>${log.target_type}</td>
|
||||
<td>${log.target_id || '-'}</td>
|
||||
<td>
|
||||
${log.details ? `<button class="btn btn-sm btn-info" onclick="showDetails('${log.details}')">查看详情</button>` : '-'}
|
||||
</td>
|
||||
<td>${log.ip_address || '-'}</td>
|
||||
<td>${log.create_time}</td>
|
||||
`;
|
||||
tbody.appendChild(tr);
|
||||
});
|
||||
}
|
||||
|
||||
// 渲染分页控件
|
||||
function renderPagination(pagination) {
|
||||
const paginationDiv = document.getElementById('pagination');
|
||||
paginationDiv.innerHTML = '';
|
||||
|
||||
if (pagination.pages <= 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 上一页按钮
|
||||
if (pagination.has_prev) {
|
||||
const prevButton = document.createElement('button');
|
||||
prevButton.className = 'btn btn-outline-primary me-1';
|
||||
prevButton.textContent = '上一页';
|
||||
prevButton.onclick = () => loadLogs(pagination.page - 1);
|
||||
paginationDiv.appendChild(prevButton);
|
||||
}
|
||||
|
||||
// 页码按钮
|
||||
for (let i = 1; i <= pagination.pages; i++) {
|
||||
const pageButton = document.createElement('button');
|
||||
pageButton.className = `btn ${i === pagination.page ? 'btn-primary' : 'btn-outline-primary'} me-1`;
|
||||
pageButton.textContent = i;
|
||||
pageButton.onclick = () => loadLogs(i);
|
||||
paginationDiv.appendChild(pageButton);
|
||||
}
|
||||
|
||||
// 下一页按钮
|
||||
if (pagination.has_next) {
|
||||
const nextButton = document.createElement('button');
|
||||
nextButton.className = 'btn btn-outline-primary ms-1';
|
||||
nextButton.textContent = '下一页';
|
||||
nextButton.onclick = () => loadLogs(pagination.page + 1);
|
||||
paginationDiv.appendChild(nextButton);
|
||||
}
|
||||
}
|
||||
|
||||
// 显示详情
|
||||
function showDetails(details) {
|
||||
try {
|
||||
const parsedDetails = JSON.parse(details);
|
||||
alert(JSON.stringify(parsedDetails, null, 2));
|
||||
} catch (e) {
|
||||
alert(details);
|
||||
}
|
||||
}
|
||||
|
||||
// 查看系统日志
|
||||
function viewSystemLogs() {
|
||||
apiRequest('/api/v1/logs/file')
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
document.getElementById('systemLogContent').textContent = data.data.content;
|
||||
new bootstrap.Modal(document.getElementById('systemLogModal')).show();
|
||||
} else {
|
||||
alert('加载系统日志失败: ' + data.message);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('加载系统日志失败:', error);
|
||||
alert('加载系统日志失败,请稍后重试');
|
||||
});
|
||||
}
|
||||
</script>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user