feat: initial commit
This commit is contained in:
@@ -0,0 +1,477 @@
|
||||
<?php
|
||||
require_once("cong.php");
|
||||
session_start();
|
||||
|
||||
if(empty($_SESSION['password']) || $_SESSION['password'] != LOGIN_PASSWORD) {
|
||||
unset($_SESSION['password']);
|
||||
unset($_SESSION['check_result']);
|
||||
echo("<script language=javascript>alert('密码错误!');window.location='ip_check_edit.php'; </script>");
|
||||
//die("输入的密码不正确,请重新输入。");
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>访问判断日志</title>
|
||||
<meta name="renderer" content="webkit">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link href="//cdn.staticfile.org/layui/2.9.2/css/layui.css" rel="stylesheet">
|
||||
<style>
|
||||
:root {
|
||||
--log-primary: #16baaa;
|
||||
--log-primary-dark: #0e8d81;
|
||||
--log-bg: #f0f2f5;
|
||||
--log-card: #ffffff;
|
||||
--log-border: #e8ecf1;
|
||||
--log-header-bg: #f4f7fb;
|
||||
--log-text: #2c3e50;
|
||||
--log-muted: #8c98a4;
|
||||
}
|
||||
* { box-sizing: border-box; }
|
||||
body {
|
||||
margin: 0;
|
||||
background: var(--log-bg);
|
||||
color: var(--log-text);
|
||||
font-family: 'Segoe UI', system-ui, -apple-system, sans-serif;
|
||||
}
|
||||
.log-page {
|
||||
max-width: 1680px;
|
||||
margin: 0 auto;
|
||||
padding: 24px 28px 40px;
|
||||
}
|
||||
.log-page-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 20px;
|
||||
flex-wrap: wrap;
|
||||
gap: 12px;
|
||||
}
|
||||
.log-page-header h1 {
|
||||
margin: 0;
|
||||
font-size: 1.35rem;
|
||||
font-weight: 600;
|
||||
color: var(--log-text);
|
||||
}
|
||||
.log-page-header p {
|
||||
margin: 4px 0 0;
|
||||
font-size: .85rem;
|
||||
color: var(--log-muted);
|
||||
}
|
||||
.log-card {
|
||||
background: var(--log-card);
|
||||
border: 1px solid var(--log-border);
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 2px 12px rgba(15, 23, 42, .04);
|
||||
margin-bottom: 16px;
|
||||
overflow: hidden;
|
||||
}
|
||||
.log-card-body { padding: 18px 20px; }
|
||||
.log-filter-grid .layui-col-md3 { margin-bottom: 12px; }
|
||||
.log-filter-grid .layui-input,
|
||||
.log-filter-grid .layui-select-title input {
|
||||
border-radius: 6px;
|
||||
border-color: var(--log-border);
|
||||
}
|
||||
.log-actions {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 14px 20px;
|
||||
border-top: 1px solid var(--log-border);
|
||||
background: #fafbfc;
|
||||
}
|
||||
.log-actions .layui-btn { border-radius: 6px; }
|
||||
.log-actions .layui-btn-primary { background: #fff; }
|
||||
.log-count {
|
||||
margin-left: auto;
|
||||
font-size: .88rem;
|
||||
color: var(--log-muted);
|
||||
}
|
||||
.log-count strong {
|
||||
color: var(--log-primary-dark);
|
||||
font-size: 1rem;
|
||||
margin: 0 4px;
|
||||
}
|
||||
#btn-clear { background: #e74c3c !important; border-color: #e74c3c !important; }
|
||||
.log-table-wrap { padding: 0; }
|
||||
.log-table-wrap .layui-table-view {
|
||||
border: none;
|
||||
border-radius: 0 0 10px 10px;
|
||||
margin: 0;
|
||||
}
|
||||
/* Sticky header */
|
||||
.log-table-wrap .layui-table-header {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 20;
|
||||
border-radius: 0;
|
||||
}
|
||||
.log-table-wrap .layui-table-header .layui-table {
|
||||
background: linear-gradient(180deg, #eef3f9 0%, #e4ebf5 100%);
|
||||
}
|
||||
.log-table-wrap .layui-table-header th {
|
||||
color: #3d5167 !important;
|
||||
font-weight: 600 !important;
|
||||
font-size: 12.5px;
|
||||
border-color: #d8e0ea !important;
|
||||
padding: 11px 10px !important;
|
||||
}
|
||||
/* Zebra + hover */
|
||||
.log-table-wrap .layui-table-body tr:nth-child(even) td {
|
||||
background-color: #fafbfc;
|
||||
}
|
||||
.log-table-wrap .layui-table-body tr:hover td {
|
||||
background-color: #eef6ff !important;
|
||||
}
|
||||
.log-table-wrap .layui-table-body td {
|
||||
border-color: #eef1f5 !important;
|
||||
padding: 9px 10px !important;
|
||||
font-size: 12.5px;
|
||||
line-height: 1.45;
|
||||
transition: background-color .15s ease;
|
||||
}
|
||||
.log-table-wrap .layui-table-page {
|
||||
border-top: 1px solid var(--log-border);
|
||||
padding: 12px 16px;
|
||||
background: #fafbfc;
|
||||
}
|
||||
/* Badges */
|
||||
.cloak-badge {
|
||||
display: inline-block;
|
||||
padding: 2px 9px;
|
||||
border-radius: 999px;
|
||||
font-size: 11.5px;
|
||||
font-weight: 600;
|
||||
line-height: 1.5;
|
||||
white-space: nowrap;
|
||||
letter-spacing: .02em;
|
||||
}
|
||||
.badge-success { background: #d4edda; color: #155724; }
|
||||
.badge-error { background: #f8d7da; color: #721c24; }
|
||||
.badge-warning { background: #fff3cd; color: #856404; }
|
||||
.badge-info { background: #d1ecf1; color: #0c5460; }
|
||||
.badge-muted { background: #e9ecef; color: #495057; }
|
||||
.reason-badge {
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
vertical-align: middle;
|
||||
}
|
||||
/* Truncation + mono timestamp */
|
||||
.cell-ellipsis {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
cursor: default;
|
||||
}
|
||||
.cell-mono {
|
||||
font-family: 'SF Mono', 'Consolas', 'Monaco', monospace;
|
||||
font-size: 12px;
|
||||
color: #4a5568;
|
||||
letter-spacing: -.02em;
|
||||
}
|
||||
.cell-ip { font-family: 'SF Mono', 'Consolas', monospace; font-size: 12px; }
|
||||
.text-muted { color: #adb5bd; }
|
||||
@media (max-width: 768px) {
|
||||
.log-page { padding: 16px 12px 32px; }
|
||||
.log-count { margin-left: 0; width: 100%; }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="log-page">
|
||||
<div class="log-page-header">
|
||||
<div>
|
||||
<h1>访问判断日志</h1>
|
||||
<p>访客判定记录 · 支持筛选、导出与分页浏览</p>
|
||||
</div>
|
||||
<div class="log-nav" style="display:flex;gap:8px;">
|
||||
<a href="table.php" style="display:inline-block;padding:6px 14px;border-radius:6px;font-size:.85rem;text-decoration:none;border:1px solid #e8ecf1;background:#16baaa;color:#fff;">访问日志</a>
|
||||
<a href="log_analytics.php" style="display:inline-block;padding:6px 14px;border-radius:6px;font-size:.85rem;text-decoration:none;border:1px solid #e8ecf1;background:#fff;color:#2c3e50;">数据分析</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="log-card">
|
||||
<div class="log-card-body">
|
||||
<form class="layui-form layui-row layui-col-space16 log-filter-grid">
|
||||
<div class="layui-col-md3">
|
||||
<div class="layui-input-wrap">
|
||||
<div class="layui-input-prefix">
|
||||
<i class="layui-icon layui-icon-username"></i>
|
||||
</div>
|
||||
<input type="text" name="domain" value="" placeholder="域名" class="layui-input" lay-affix="clear">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-col-md3">
|
||||
<div class="layui-input-wrap">
|
||||
<input type="text" name="spage" value="" placeholder="访问页面,可输入配置名称搜索" class="layui-input" lay-affix="clear">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-col-md3">
|
||||
<div class="layui-input-wrap">
|
||||
<select name="result">
|
||||
<option value="">全部(不含检测中)</option>
|
||||
<option value="true">TRUE(通过访问)</option>
|
||||
<option value="false">FALSE(禁止访问)</option>
|
||||
<option value="wait">检测中</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-col-md3">
|
||||
<div class="layui-input-wrap">
|
||||
<input type="text" name="country" placeholder="国家" lay-affix="clear" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-col-md3">
|
||||
<div class="layui-input-wrap">
|
||||
<input type="text" name="IP" placeholder="IP" lay-affix="clear" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-col-md3">
|
||||
<div class="layui-input-wrap">
|
||||
<div class="layui-input-prefix">
|
||||
<i class="layui-icon layui-icon-date"></i>
|
||||
</div>
|
||||
<input type="text" name="visit_date" readonly placeholder="访问日期" class="layui-input demo-table-search-date">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-btn-container layui-col-xs12">
|
||||
<a class="layui-btn" lay-submit href="javascript:void(0);" id="export" target="_blank">导出</a>
|
||||
<button class="layui-btn" lay-submit lay-filter="demo-table-search">搜索</button>
|
||||
<button type="reset" class="layui-btn layui-btn-primary">清除条件</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="log-actions">
|
||||
<button class="layui-btn layui-btn-sm" id="btn-refresh" onclick="resetTable()" lay-event="footerDemoBtn1">刷新</button>
|
||||
<button class="layui-btn layui-btn-sm layui-btn-normal" id="btn-show-more" type="button">显示更多</button>
|
||||
<button class="layui-btn layui-btn-sm btn-danger" id="btn-clear" lay-on="confirm" lay-event="footerDemoBtn2">清空数据库</button>
|
||||
<span class="log-count">当前查询数量:<strong id="total_nums">—</strong></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="log-card log-table-wrap">
|
||||
<div id="demo-laypage-all"></div>
|
||||
<table class="layui-hide" id="ID-table-demo-search" lay-filter="test"></table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="/dist/layui.js"></script>
|
||||
<script src="/dist/jquery.min.js"></script>
|
||||
<script>
|
||||
|
||||
layui.use(function(){
|
||||
var table = layui.table;
|
||||
var form = layui.form;
|
||||
var laydate = layui.laydate;
|
||||
var showMoreCols = false;
|
||||
|
||||
function escapeHtml(s) {
|
||||
if (s == null || s === '') return '';
|
||||
return String(s)
|
||||
.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/"/g, '"');
|
||||
}
|
||||
|
||||
function cellEllipsis(value, maxLen) {
|
||||
var text = value == null ? '' : String(value);
|
||||
if (!text) return '<span class="text-muted">—</span>';
|
||||
var esc = escapeHtml(text);
|
||||
var display = text.length > maxLen ? escapeHtml(text.slice(0, maxLen)) + '…' : esc;
|
||||
return '<span class="cell-ellipsis" title="' + esc + '">' + display + '</span>';
|
||||
}
|
||||
|
||||
function badgeResult(val) {
|
||||
var raw = val == null ? '' : String(val);
|
||||
var v = raw.toLowerCase();
|
||||
if (v === 'true' || v === '1') {
|
||||
return '<span class="cloak-badge badge-success">TRUE</span>';
|
||||
}
|
||||
if (v === 'false' || v === '0') {
|
||||
return '<span class="cloak-badge badge-error">FALSE</span>';
|
||||
}
|
||||
if (v === 'wait' || raw.indexOf('检测') !== -1) {
|
||||
return '<span class="cloak-badge badge-info">检测中</span>';
|
||||
}
|
||||
return '<span class="cloak-badge badge-muted">' + escapeHtml(raw) + '</span>';
|
||||
}
|
||||
|
||||
function badgeReason(reason) {
|
||||
if (reason == null || reason === '') {
|
||||
return '<span class="text-muted">—</span>';
|
||||
}
|
||||
var text = String(reason);
|
||||
var cls = 'badge-info';
|
||||
if (text.indexOf('未确定流量来源') !== -1) {
|
||||
cls = 'badge-warning';
|
||||
} else if (/过滤|黑名单|无效|代理|VPN|禁止|欺骗|无来源/i.test(text)) {
|
||||
cls = 'badge-error';
|
||||
} else if (/白名单|允许|通过/i.test(text)) {
|
||||
cls = 'badge-success';
|
||||
}
|
||||
var esc = escapeHtml(text);
|
||||
var short = text.length > 26 ? escapeHtml(text.slice(0, 26)) + '…' : esc;
|
||||
return '<span class="cloak-badge ' + cls + ' reason-badge" title="' + esc + '">' + short + '</span>';
|
||||
}
|
||||
|
||||
function buildCols(showMore) {
|
||||
return [[
|
||||
{field:'id', title: 'ID', width:56, fixed: true},
|
||||
{field:'domain', title: '域名', width:120, templet: function(d){ return cellEllipsis(d.domain, 18); }},
|
||||
{field:'visit_date', title: '访问日期', width:130, templet: function(d){
|
||||
return '<span class="cell-mono" title="' + escapeHtml(d.visit_date) + '">' + escapeHtml(d.visit_date) + '</span>';
|
||||
}},
|
||||
{field:'country', title: '国家', width:100, templet: function(d){ return cellEllipsis(d.country, 12); }},
|
||||
{field:'result', title: '是否正常', width:88, templet: function(d){ return badgeResult(d.result); }},
|
||||
{field:'reason', title: '理由', width:140, templet: function(d){ return badgeReason(d.reason); }},
|
||||
{field:'judge_timing_text', title: '判断用时', width:240, templet: function(d){ return cellEllipsis(d.judge_timing_text, 36); }},
|
||||
{field:'vtimes', title: '第几次访问', width:96},
|
||||
{field:'fp_url', title: '跳转至', width:180, templet: function(d){ return cellEllipsis(d.fp_url, 28); }},
|
||||
{field:'device', title: '访问设备', width:200, templet: function(d){ return cellEllipsis(d.device, 32); }},
|
||||
{field:'referer', title: '来源', width:200, templet: function(d){ return cellEllipsis(d.referer, 32); }},
|
||||
{field:'IP', title: 'IP(支持IPV6)', width:130, templet: function(d){
|
||||
return '<span class="cell-ip" title="' + escapeHtml(d.IP) + '">' + escapeHtml(d.IP) + '</span>';
|
||||
}},
|
||||
{field:'client', title: '客户端', width:80, templet: function(d){ return cellEllipsis(d.client, 10); }},
|
||||
{field:'language', title: '语言', width:80, templet: function(d){ return cellEllipsis(d.language, 10); }},
|
||||
{field:'browser', title: '浏览器', width:88, templet: function(d){ return cellEllipsis(d.browser, 10); }},
|
||||
{field:'page', title: '访问页面', width:200, templet: function(d){ return cellEllipsis(d.page, 32); }},
|
||||
{field:'campagin_id', title: '广告策略', width:88, templet: function(d){ return cellEllipsis(d.campagin_id, 10); }},
|
||||
{field:'user_agent', title: 'User-Agent', width:320, hide: !showMore, templet: function(d){ return cellEllipsis(d.user_agent, 48); }},
|
||||
{field:'http_referer', title: 'HTTP-Referer', width:260, hide: !showMore, templet: function(d){ return cellEllipsis(d.http_referer, 40); }},
|
||||
{field:'accept_language_raw', title: 'Accept-Language', width:220, hide: !showMore, templet: function(d){ return cellEllipsis(d.accept_language_raw, 32); }},
|
||||
]];
|
||||
}
|
||||
|
||||
table.render({
|
||||
elem: '#ID-table-demo-search',
|
||||
url: 'datatable/datalist.php',
|
||||
cols: buildCols(false),
|
||||
page: true,
|
||||
limit: 50,
|
||||
height: 800,
|
||||
size: "sm",
|
||||
skin: "line",
|
||||
even: true,
|
||||
rowStyle: function(row) {
|
||||
if (row.reason && row.reason.indexOf('未确定流量来源') !== -1) {
|
||||
return 'color:#856404;background-color:#fff8e6;';
|
||||
}
|
||||
},
|
||||
done: function(res, curr, count, origin){
|
||||
console.log(res); // 得到当前渲染的数据
|
||||
console.log(curr); // 得到当前页码
|
||||
console.log(count); // 得到数据总量
|
||||
console.log(origin); // 回调函数所执行的来源 --- 2.8.7+
|
||||
$("#total_nums").text(count);
|
||||
},
|
||||
});
|
||||
|
||||
$('#btn-show-more').on('click', function() {
|
||||
showMoreCols = !showMoreCols;
|
||||
$(this).text(showMoreCols ? '收起更多' : '显示更多');
|
||||
table.reload('ID-table-demo-search', { cols: buildCols(showMoreCols) });
|
||||
});
|
||||
|
||||
// 日期
|
||||
laydate.render({
|
||||
elem: '.demo-table-search-date'
|
||||
});
|
||||
// 搜索提交
|
||||
form.on('submit(demo-table-search)', function(data){
|
||||
var field = data.field; // 获得表单字段
|
||||
// 执行搜索重载
|
||||
table.reload('ID-table-demo-search', {
|
||||
page: {
|
||||
curr: 1 // 重新从第 1 页开始
|
||||
},
|
||||
where: field // 搜索的字段
|
||||
});
|
||||
// layer.msg('搜索成功<br>此处为静态模拟数据,实际使用时换成真实接口即可');
|
||||
return false; // 阻止默认 form 跳转
|
||||
});
|
||||
// table.reload('ID-table-demo-search', {
|
||||
// page: {
|
||||
// curr: 1 // 重新从第 1 页开始
|
||||
// },
|
||||
// });
|
||||
var layer = layui.layer;
|
||||
var util = layui.util;
|
||||
util.on('lay-on', {
|
||||
confirm: function(){
|
||||
layer.confirm('确定清除所有日志数据?', {
|
||||
btn: ['确定', '关闭'] //按钮
|
||||
}, function(){
|
||||
$.get("datatable/datalist.php", {clear: "true"}, function(result){
|
||||
layer.msg('清除成功', {icon: 1});
|
||||
window.location.reload();
|
||||
});
|
||||
}, function(){
|
||||
|
||||
});
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
// 刷新按钮
|
||||
function resetTable() {
|
||||
var table = layui.table;
|
||||
table.reload('ID-table-demo-search', {
|
||||
page: {
|
||||
curr: 1 // 重新从第 1 页开始
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
$("#export").click(function() {
|
||||
var visit_date = $("input[name=visit_date]").val();
|
||||
var domain = $("input[name=domain]").val();
|
||||
var spage = $("input[name=spage]").val();
|
||||
var country = $("input[name=country]").val();
|
||||
var IP = $("input[name=IP]").val();
|
||||
var result = $("select[name=result]").val();
|
||||
|
||||
var url = 'datatable/export.php?';
|
||||
var args = [];
|
||||
|
||||
if(visit_date) {
|
||||
args.push( "visit_date=" + visit_date );
|
||||
}
|
||||
|
||||
if(domain) {
|
||||
args.push( "domain=" + domain );
|
||||
}
|
||||
|
||||
if(spage) {
|
||||
args.push( "spage=" + spage );
|
||||
}
|
||||
|
||||
if(country) {
|
||||
args.push( "country=" + country );
|
||||
}
|
||||
|
||||
if(IP) {
|
||||
args.push( "IP=" + IP );
|
||||
}
|
||||
|
||||
if(result) {
|
||||
args.push( "result=" + encodeURIComponent(result) );
|
||||
}
|
||||
|
||||
window.location.href=url + args.join("&");
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user