// 操作日志管理 (() => { let currentPage = 1; const pageSize = 50; Router.register('/system/operations-log', async () => { const html = `
ID 用户 操作类型 操作详情 操作时间
加载中...
`; setTimeout(() => { loadLogs(); document.getElementById('search-btn')?.addEventListener('click', () => { currentPage = 1; loadLogs(); }); document.getElementById('keyword-filter')?.addEventListener('keypress', (e) => { if (e.key === 'Enter') { currentPage = 1; loadLogs(); } }); document.getElementById('cleanup-btn')?.addEventListener('click', cleanupLogs); document.getElementById('prev-btn')?.addEventListener('click', () => { if (currentPage > 1) { currentPage--; loadLogs(); } }); document.getElementById('next-btn')?.addEventListener('click', () => { currentPage++; loadLogs(); }); }, 100); return html; }); // 操作类型中文映射 const actionLabels = { 'login': '登录', 'logout': '登出', 'create_customer_order': '创建客户订单', 'update_customer_order': '更新客户订单', 'delete_customer_order': '删除客户订单', 'create_reconciliation': '创建对账单', 'update_reconciliation': '更新对账单', 'delete_reconciliation': '删除对账单', 'batch_delete_reconciliation': '批量删除对账单', 'batch_delete_reconciliations': '批量删除对账单', 'create_work_order': '创建工单', 'update_work_order': '更新工单', 'delete_work_order': '删除工单', 'confirm_work_order': '确认工单', 'create_bom': '创建BOM', 'update_bom': '更新BOM', 'delete_bom': '删除BOM', 'import_bom': '导入BOM', 'create_initial_stock': '创建期初库存', 'update_initial_stock': '更新期初库存', 'delete_initial_stock': '删除期初库存', 'import_initial_stock': '导入期初库存', 'create_purchase_demand': '创建采购需求', 'update_purchase_demand': '更新采购需求', 'delete_purchase_demand': '删除采购需求', 'create_material_purchase': '创建物料采购', 'update_material_purchase': '更新物料采购', 'delete_material_purchase': '删除物料采购', 'batch_delete_material_purchase': '批量删除物料采购', 'import_material_purchase': '导入物料采购', 'cleanup_operations_log': '清理操作日志', 'add_personnel': '添加人员', 'upload_sop': '上传SOP', 'delete_sop': '删除SOP', 'upload_mac': '上传MAC', 'upload_stats': '上传统计', 'upload_repairs': '上传返修', 'upload_shipments': '上传发货', 'create_shipment': '创建发货', 'delete_shipment': '删除发货', 'clear_redis': '清空缓存', 'audit_yt_cost': '审核易泰勒成本', 'audit_yt_probe': '审核易泰勒探针', 'audit_pdd_cost': '审核拼多多成本', 'audit_pdd_probe': '审核拼多多探针', 'upload_shipment': '上传发货记录' }; function getActionLabel(action) { return actionLabels[action] || action; } async function loadLogs() { try { const keyword = document.getElementById('keyword-filter')?.value || ''; const res = await fetch(`/api/operations-log?page=${currentPage}&page_size=${pageSize}&keyword=${encodeURIComponent(keyword)}`); const data = await res.json(); const tbody = document.getElementById('log-list'); if (!tbody) return; if (!data.list || data.list.length === 0) { tbody.innerHTML = '暂无数据'; updatePagination(0); return; } tbody.innerHTML = data.list.map(log => ` ${log.id} ${log.username || '—'} ${getActionLabel(log.action)} ${log.detail || '—'} ${formatTime(log.ts)} `).join(''); updatePagination(data.total); } catch (err) { console.error('加载操作日志失败:', err); API.toast('加载失败', 'error'); } } function updatePagination(total) { const pageInfo = document.getElementById('page-info'); const prevBtn = document.getElementById('prev-btn'); const nextBtn = document.getElementById('next-btn'); const totalPages = Math.ceil(total / pageSize); if (pageInfo) { pageInfo.textContent = `共 ${total} 条记录,第 ${currentPage}/${totalPages || 1} 页`; } if (prevBtn) { prevBtn.disabled = currentPage <= 1; } if (nextBtn) { nextBtn.disabled = currentPage >= totalPages; } } function formatTime(ts) { if (!ts) return '—'; try { const date = new Date(ts); return date.toLocaleString('zh-CN', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit' }); } catch { return ts; } } function escapeHtml(str) { if (!str) return ''; return str.replace(/&/g, '&') .replace(//g, '>') .replace(/"/g, '"'); } async function cleanupLogs() { if (!confirm('确定要清理3个月前的旧日志吗?此操作不可恢复。')) { return; } try { const res = await fetch('/api/operations-log/cleanup', { method: 'DELETE' }); const data = await res.json(); if (res.ok && data.ok) { API.toast(data.message, 'success'); loadLogs(); } else { API.toast(data.error || '清理失败', 'error'); } } catch (err) { console.error('清理日志失败:', err); API.toast('清理失败', 'error'); } } })();