<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>授权码操作日志</title> <link rel="stylesheet" href="/static/layui/css/layui.css"> <link rel="stylesheet" href="/static/css/style.css"> </head> <body> <div class="layui-fluid"> <div class="layui-card"> <div class="layui-card-header"> <span>授权码操作日志</span> <div class="layui-btn-group"> <button class="layui-btn layui-btn-sm" id="refresh-logs"> <i class="layui-icon"></i> 刷新 </button> <button class="layui-btn layui-btn-sm layui-btn-normal" id="export-logs"> <i class="layui-icon"></i> 导出 </button> </div> </div> <div class="layui-card-body"> <!-- 搜索表单 --> <form class="layui-form layui-form-pane" action=""> <div class="layui-form-item"> <div class="layui-inline"> <label class="layui-form-label">操作类型</label> <div class="layui-input-inline"> <select name="action"> <option value="">全部</option> <option value="create">创建</option> <option value="use">使用</option> <option value="verify">验证</option> <option value="revoke">撤销</option> </select> </div> </div> <div class="layui-inline"> <label class="layui-form-label">状态</label> <div class="layui-input-inline"> <select name="status"> <option value="">全部</option> <option value="success">成功</option> <option value="failed">失败</option> </select> </div> </div> <div class="layui-inline"> <label class="layui-form-label">设备UID</label> <div class="layui-input-inline"> <input type="text" name="device_uid" autocomplete="off" class="layui-input"> </div> </div> <div class="layui-inline"> <button class="layui-btn" lay-submit lay-filter="search"> <i class="layui-icon"></i> 搜索 </button> </div> </div> </form> <!-- 数据表格 --> <table id="log-table" lay-filter="log-table"></table> </div> </div> </div> <!-- 操作类型模板 --> <script type="text/html" id="actionTpl"> {{# var types = { 'create': '<span class="layui-badge layui-bg-blue">创建</span>', 'use': '<span class="layui-badge layui-bg-green">使用</span>', 'verify': '<span class="layui-badge layui-bg-orange">验证</span>', 'revoke': '<span class="layui-badge layui-bg-red">撤销</span>' }; }} {{# return types[d.action] || d.action; }} </script> <!-- 状态模板 --> <script type="text/html" id="statusTpl"> {{# if(d.status === 'success'){ }} <span class="layui-badge layui-bg-green">成功</span> {{# } else { }} <span class="layui-badge layui-bg-red">失败</span> {{# } }} </script> <script src="/static/layui/layui.js"></script> <script> layui.use(['table', 'layer', 'form'], function(){ var table = layui.table; var layer = layui.layer; var form = layui.form; var $ = layui.$; // 获取授权码ID var licenseId = location.search.match(/id=(\d+)/)[1]; // 初始化表格 var tableIns = table.render({ elem: '#log-table', url: '/api/licenses/' + licenseId + '/logs', headers: { 'Authorization': 'Bearer ' + localStorage.getItem('token') }, cols: [[ {field: 'action', title: '操作类型', width: 100, templet: '#actionTpl', sort: true}, {field: 'device_uid', title: '设备UID', width: 180}, {field: 'ip', title: 'IP地址', width: 150}, {field: 'status', title: '状态', width: 100, templet: '#statusTpl'}, {field: 'message', title: '详细信息'}, {field: 'created_at', title: '操作时间', width: 180, sort: true, templet: function(d){ return new Date(d.created_at).toLocaleString(); }} ]], page: true, parseData: function(res) { if (res.code === 401) { window.location.href = '/login'; return; } return res; } }); // 搜索表单提交 form.on('submit(search)', function(data){ tableIns.reload({ where: data.field, page: { curr: 1 } }); return false; }); // 刷新按钮点击事件 $('#refresh-logs').on('click', function(){ tableIns.reload(); }); // 导出按钮点击事件 $('#export-logs').on('click', function(){ var loadIndex = layer.load(2); fetch('/api/licenses/' + licenseId + '/logs?export=1', { headers: { 'Authorization': 'Bearer ' + localStorage.getItem('token') } }) .then(response => response.blob()) .then(blob => { layer.close(loadIndex); var url = window.URL.createObjectURL(blob); var a = document.createElement('a'); a.href = url; a.download = 'license_logs_' + licenseId + '_' + new Date().toISOString().slice(0,19).replace(/[-:]/g, '') + '.csv'; document.body.appendChild(a); a.click(); window.URL.revokeObjectURL(url); document.body.removeChild(a); }) .catch(error => { layer.close(loadIndex); layer.msg('导出失败:' + error.message); }); }); }); </script> </body> </html>