<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>操作日志</title>
    <link rel="stylesheet" href="{{ asset('CmsProUi/component/pear/css/pear.css') }}">
    <link rel="stylesheet" href="{{ asset('CmsProUi/font-awesome/4.7.0/css/font-awesome.min.css') }}">
    <link rel="stylesheet" href="{{ asset('Admin/css/admin.css') }}">
    <link rel="stylesheet" href="{{ asset('Admin/css/variables.css') }}">
    <link rel="stylesheet" href="{{ asset('Admin/css/reset.css') }}">
    <style>
    .detail-row { display: flex; padding: 8px 0; border-bottom: 1px solid #f0f0f0; }
    .detail-row:last-child { border-bottom: none; }
    .detail-label { width: 100px; color: #666; flex-shrink: 0; text-align: right; padding-right: 12px; }
    .detail-value { flex: 1; word-break: break-all; }
    .status-success { color: #16b777; }
    .status-fail { color: #cf1322; }
    .method-badge { padding: 2px 8px; border-radius: 3px; font-size: 12px; font-weight: bold; color: #fff; }
    .method-get { background: #1890ff; }
    .method-post { background: #16b777; }
    .method-put { background: #fa8c16; }
    .method-patch { background: #722ed1; }
    .method-delete { background: #cf1322; }
    .params-box { background: #f6f8fa; border: 1px solid #e1e4e8; border-radius: 4px; padding: 12px; font-family: Consolas, Monaco, monospace; font-size: 12px; max-height: 300px; overflow-y: auto; white-space: pre-wrap; word-break: break-all; }
</style>
    @include('admin.partials.permission-script')
</head>
<body>
<div class="pear-container">
    <div class="layui-card">
        <div class="layui-card-body">
            <form class="layui-form" action="">
                <div class="layui-inline">
                    <div class="layui-input-inline">
                        <input type="text" name="keyword" placeholder="路径/操作/IP" class="layui-input">
                    </div>
                </div>
                <div class="layui-inline">
                    <div class="layui-input-inline">
                        <select name="module">
                            <option value="">全部模块</option>
                        </select>
                    </div>
                </div>
                <div class="layui-inline">
                    <div class="layui-input-inline">
                        <select name="method">
                            <option value="">全部方法</option>
                            <option value="GET">GET</option>
                            <option value="POST">POST</option>
                            <option value="PUT">PUT</option>
                            <option value="PATCH">PATCH</option>
                            <option value="DELETE">DELETE</option>
                        </select>
                    </div>
                </div>
                <div class="layui-inline">
                    <div class="layui-input-inline">
                        <select name="status">
                            <option value="">全部状态</option>
                            <option value="1">成功</option>
                            <option value="0">失败</option>
                        </select>
                    </div>
                </div>
                <div class="layui-inline">
                    <div class="layui-input-inline" style="width: 160px;">
                        <input type="text" name="start_date" id="start-date" placeholder="开始日期" class="layui-input">
                    </div>
                </div>
                <div class="layui-inline">
                    <div class="layui-input-inline" style="width: 160px;">
                        <input type="text" name="end_date" id="end-date" placeholder="结束日期" class="layui-input">
                    </div>
                </div>
                <div class="layui-inline">
                    <button class="layui-btn layui-btn-md" lay-submit lay-filter="oplog-query">
                        <i class="layui-icon layui-icon-search"></i> 查询
                    </button>
                    <button type="reset" class="layui-btn layui-btn-md layui-btn-primary">
                        <i class="layui-icon layui-icon-refresh"></i> 重置
                    </button>
                </div>
            </form>
        </div>
    </div>

    <div class="layui-card">
        <div class="layui-card-body">
            <table id="oplog-table" lay-filter="oplog-table"></table>
        </div>
    </div>

    @verbatim
    <script type="text/html" id="oplog-toolbar">
        <button class="layui-btn layui-btn-sm layui-btn-danger" lay-event="clear" data-permission="admin.operation-log.clear">
            <i class="layui-icon layui-icon-delete"></i> 清理日志
        </button>
        <button class="layui-btn layui-btn-sm layui-btn-danger" lay-event="batchRemove" data-permission="admin.operation-log.destroy">
            <i class="layui-icon layui-icon-delete"></i> 批量删除
        </button>
    </script>

    <script type="text/html" id="oplog-bar">
        <a class="layui-btn layui-btn-xs" lay-event="view">详情</a>
        <a class="layui-btn layui-btn-xs layui-btn-danger" lay-event="del" data-permission="admin.operation-log.destroy">删除</a>
    </script>
    @endverbatim

    @verbatim
    <script type="text/html" id="oplog-method-tpl">
        <span class="method-badge method-{{ d.method.toLowerCase() }}">{{ d.method }}</span>
    </script>

    <script type="text/html" id="oplog-status-tpl">
        {{# if(d.status == 1){ }}
        <span class="status-success"><i class="fa fa-check-circle"></i> 成功</span>
        {{# } else { }}
        <span class="status-fail"><i class="fa fa-times-circle"></i> 失败</span>
        {{# } }}
    </script>

    <script type="text/html" id="oplog-user-tpl">
        {{# if(d.user){ }}{{ d.user.name || d.user.username }}{{# } else { }}-{{# } }}
    </script>
    @endverbatim
</div>
<script src="{{ asset('CmsProUi/component/layui/layui.js') }}"></script>
<script src="{{ asset('CmsProUi/component/pear/pear.js') }}"></script>
<script>
    layui.use(['table', 'form', 'jquery', 'laydate', 'layer'], function() {
        var table = layui.table;
        var form = layui.form;
        var $ = layui.jquery;
        var laydate = layui.laydate;
        var layer = layui.layer;

        $.ajaxSetup({
            headers: {
                'X-CSRF-TOKEN': '{{ csrf_token() }}'
            },
            statusCode: {
                401: function() {
                    layer.msg('登录已过期，请重新登录', {icon: 2, time: 1500}, function() {
                        window.location.href = '/admin/login?redirect=' + encodeURIComponent(window.location.pathname + window.location.search);
                    });
                }
            }
        });

        // 根据权限隐藏工具栏按钮
        $('#oplog-toolbar [data-permission]').each(function() {
            if (!window.hasPermission || !window.hasPermission($(this).data('permission'))) {
                $(this).hide();
            }
        });

        laydate.render({
            elem: '#start-date',
            type: 'date'
        });

        laydate.render({
            elem: '#end-date',
            type: 'date'
        });

        loadModules();

        table.render({
            elem: '#oplog-table',
            url: '/api/admin/operation-logs',
            toolbar: '#oplog-toolbar',
            defaultToolbar: [{
                title: '刷新',
                layEvent: 'refresh',
                icon: 'layui-icon-refresh'
            }, 'filter', 'print', 'exports'],
            page: {
                layout: ['count', 'prev', 'page', 'next', 'limit'],
                groups: 5,
                limit: 20,
                limits: [10, 20, 50, 100]
            },
            cols: [[
                { type: 'checkbox', fixed: 'left' },
                { title: 'ID', field: 'id', align: 'center', width: 80, sort: true },
                { title: '操作人', field: 'user', align: 'center', width: 110, templet: '#oplog-user-tpl' },
                { title: '模块', field: 'module', align: 'center', width: 120 },
                { title: '操作', field: 'action', align: 'center', width: 120 },
                { title: '方法', field: 'method', align: 'center', width: 100, templet: '#oplog-method-tpl' },
                { title: '路径', field: 'path', align: 'center' },
                { title: 'IP', field: 'ip', align: 'center', width: 130 },
                { title: '状态', field: 'status', align: 'center', width: 80, templet: '#oplog-status-tpl' },
                { title: '操作时间', field: 'create_time', align: 'center', width: 170, sort: true },
                { title: '操作', toolbar: '#oplog-bar', align: 'center', width: 140, fixed: 'right' }
            ]],
            parseData: function(res) {
                return {
                    "code": res.code === 0 ? 0 : 1,
                    "msg": res.message || "",
                    "count": res.data && res.data.pagination ? res.data.pagination.total : 0,
                    "data": res.data ? res.data.items : []
                };
            },
            done: function() {
                // 根据权限隐藏行内操作按钮
                $('td [data-permission]').each(function() {
                    if (!window.hasPermission || !window.hasPermission($(this).data('permission'))) {
                        $(this).hide();
                    }
                });
            }
        });

        form.on('submit(oplog-query)', function(data) {
            table.reload('oplog-table', { where: data.field, page: { curr: 1 } });
            return false;
        });

        table.on('toolbar(oplog-table)', function(obj) {
            if (obj.event === 'refresh') {
                table.reload('oplog-table');
            } else if (obj.event === 'clear') {
                clearLogs();
            } else if (obj.event === 'batchRemove') {
                batchRemove();
            }
        });

        table.on('tool(oplog-table)', function(obj) {
            if (obj.event === 'view') {
                viewDetail(obj.data.id);
            } else if (obj.event === 'del') {
                removeLog(obj.data);
            }
        });

        function loadModules() {
            $.ajax({
                url: '/api/admin/operation-logs/modules',
                type: 'GET',
                dataType: 'json',
                success: function(res) {
                    if (res.code === 0 && res.data) {
                        var $select = $('select[name="module"]');
                        $select.find('option:not(:first)').remove();
                        for (var i = 0; i < res.data.length; i++) {
                            $select.append('<option value="' + res.data[i] + '">' + res.data[i] + '</option>');
                        }
                        form.render('select');
                    }
                }
            });
        }

        function viewDetail(id) {
            var loadingIdx = layer.load(2);
            $.ajax({
                url: '/api/admin/operation-logs/' + id,
                type: 'GET',
                dataType: 'json',
                success: function(res) {
                    layer.close(loadingIdx);
                    if (res.code === 0 && res.data) {
                        var d = res.data;
                        var userName = d.user ? (d.user.name || d.user.username) : '-';
                        var statusHtml = d.status == 1
                            ? '<span class="status-success"><i class="fa fa-check-circle"></i> 成功</span>'
                            : '<span class="status-fail"><i class="fa fa-times-circle"></i> 失败</span>';
                        var methodHtml = '<span class="method-badge method-' + (d.method || '').toLowerCase() + '">' + d.method + '</span>';
                        var paramsHtml = d.params ? JSON.stringify(d.params, null, 2) : '无';

                        var html = '<div style="padding: 15px;">' +
                            '<div class="detail-row"><div class="detail-label">ID：</div><div class="detail-value">' + d.id + '</div></div>' +
                            '<div class="detail-row"><div class="detail-label">操作人：</div><div class="detail-value">' + userName + '</div></div>' +
                            '<div class="detail-row"><div class="detail-label">模块：</div><div class="detail-value">' + (d.module || '-') + '</div></div>' +
                            '<div class="detail-row"><div class="detail-label">操作：</div><div class="detail-value">' + (d.action || '-') + '</div></div>' +
                            '<div class="detail-row"><div class="detail-label">请求方法：</div><div class="detail-value">' + methodHtml + '</div></div>' +
                            '<div class="detail-row"><div class="detail-label">请求路径：</div><div class="detail-value">' + (d.path || '-') + '</div></div>' +
                            '<div class="detail-row"><div class="detail-label">IP地址：</div><div class="detail-value">' + (d.ip || '-') + '</div></div>' +
                            '<div class="detail-row"><div class="detail-label">User-Agent：</div><div class="detail-value" style="font-size: 12px; color: #999;">' + (d.user_agent || '-') + '</div></div>' +
                            '<div class="detail-row"><div class="detail-label">状态：</div><div class="detail-value">' + statusHtml + '</div></div>';

                        if (d.status == 0 && d.error_message) {
                            html += '<div class="detail-row"><div class="detail-label">错误信息：</div><div class="detail-value" style="color: #cf1322;">' + escapeHtml(d.error_message) + '</div></div>';
                        }

                        html += '<div class="detail-row"><div class="detail-label">操作时间：</div><div class="detail-value">' + (d.create_time || '-') + '</div></div>' +
                            '<div class="detail-row"><div class="detail-label">请求参数：</div><div class="detail-value"><div class="params-box">' + escapeHtml(paramsHtml) + '</div></div></div>' +
                            '</div>';

                        layer.open({
                            type: 1,
                            title: '操作日志详情',
                            area: ['700px', '80%'],
                            maxmin: true,
                            content: html
                        });
                    } else {
                        layer.msg(res.message || '获取详情失败', { icon: 2, time: 1500 });
                    }
                },
                error: function() {
                    layer.close(loadingIdx);
                    layer.msg('请求失败', { icon: 2, time: 1500 });
                }
            });
        }

        function removeLog(data) {
            layer.confirm('确定要删除该操作日志吗？', {
                icon: 3,
                title: '确认删除',
                btn: ['确定', '取消']
            }, function(index) {
                layer.close(index);
                var loadingIdx = layer.load(2);
                $.ajax({
                    url: '/api/admin/operation-logs/destroy',
                    type: 'DELETE',
                    data: { id: data.id },
                    dataType: 'json',
                    success: function(res) {
                        layer.close(loadingIdx);
                        if (res.code === 0) {
                            layer.msg('删除成功', { icon: 1, time: 1000 }, function() {
                                table.reload('oplog-table');
                            });
                        } else {
                            layer.msg(res.message || '删除失败', { icon: 2, time: 1500 });
                        }
                    },
                    error: function() {
                        layer.close(loadingIdx);
                        layer.msg('请求失败', { icon: 2, time: 1500 });
                    }
                });
            });
        }

        function batchRemove() {
            var checkData = table.checkStatus('oplog-table').data;
            if (checkData.length === 0) {
                layer.msg('未选中数据', { icon: 3, time: 1000 });
                return;
            }
            var ids = checkData.map(function(item) { return item.id; });
            layer.confirm('确定要删除选中的 ' + ids.length + ' 条日志吗？', {
                icon: 3,
                title: '确认删除',
                btn: ['确定', '取消']
            }, function(index) {
                layer.close(index);
                var loadingIdx = layer.load(2);
                $.ajax({
                    url: '/api/admin/operation-logs/destroy',
                    type: 'DELETE',
                    data: { ids: ids },
                    dataType: 'json',
                    success: function(res) {
                        layer.close(loadingIdx);
                        if (res.code === 0) {
                            layer.msg('删除成功', { icon: 1, time: 1000 }, function() {
                                table.reload('oplog-table');
                            });
                        } else {
                            layer.msg(res.message || '删除失败', { icon: 2, time: 1500 });
                        }
                    },
                    error: function() {
                        layer.close(loadingIdx);
                        layer.msg('请求失败', { icon: 2, time: 1500 });
                    }
                });
            });
        }

        function clearLogs() {
            layer.confirm('将清理指定天数之前的操作日志，请输入保留天数：', {
                icon: 3,
                title: '清理操作日志',
                btn: ['确定', '取消'],
                content: '<div style="padding: 15px;"><input type="number" id="clear-days" class="layui-input" value="30" placeholder="保留最近N天的日志" style="width: 200px;"></div>'
            }, function(index) {
                var days = $('#clear-days').val() || 30;
                layer.close(index);
                var loadingIdx = layer.load(2);
                $.ajax({
                    url: '/api/admin/operation-logs/clear',
                    type: 'POST',
                    data: { days: days },
                    dataType: 'json',
                    success: function(res) {
                        layer.close(loadingIdx);
                        if (res.code === 0) {
                            layer.msg(res.message || '清理成功', { icon: 1, time: 1500 }, function() {
                                table.reload('oplog-table');
                            });
                        } else {
                            layer.msg(res.message || '清理失败', { icon: 2, time: 1500 });
                        }
                    },
                    error: function() {
                        layer.close(loadingIdx);
                        layer.msg('请求失败', { icon: 2, time: 1500 });
                    }
                });
            });
        }

        function escapeHtml(text) {
            if (typeof text !== 'string') return text;
            var div = document.createElement('div');
            div.appendChild(document.createTextNode(text));
            return div.innerHTML;
        }
    });
</script>
</body>
</html>
