feat(#IWOOT): 增加网站分析页面
#Comment comment #IWOOT #Issue close https://gitee.com/LongbowEnterprise/dashboard/issues?id=IWOOT
This commit is contained in:
parent
0587bf6bde
commit
471aee2938
Binary file not shown.
|
@ -128,6 +128,12 @@ namespace Bootstrap.Admin.Controllers
|
|||
/// <returns></returns>
|
||||
public ActionResult Online() => View(new NavigatorBarModel(this));
|
||||
|
||||
/// <summary>
|
||||
/// 网站分析统计
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public ActionResult Analyse() => View(new NavigatorBarModel(this));
|
||||
|
||||
/// <summary>
|
||||
/// 用于测试ExceptionFilter
|
||||
/// </summary>
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
using Bootstrap.DataAccess;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Bootstrap.Admin.Controllers.Api
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
public class AnalyseController : ControllerBase
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet()]
|
||||
public ActionResult<AnalyseData> Get([FromQuery]string logType)
|
||||
{
|
||||
var ret = new AnalyseData();
|
||||
if (logType.Equals("LoginUsers", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var loginUsers = LoginHelper.RetrieveAll(null, null, null);
|
||||
var temp = loginUsers.GroupBy(usr => usr.LoginTime.ToString("yyyy-MM-dd"));
|
||||
var max = temp.Any() ? temp.Max(g => g.Count()) : 1;
|
||||
ret.Polylines = temp.Select((g, index) =>
|
||||
{
|
||||
ret.Datas.Add(new KeyValuePair<string, string>(g.Key, g.Count().ToString()));
|
||||
return $"{index * 2},{Math.Round(g.Count() * 28.0 / max, 2)}";
|
||||
});
|
||||
}
|
||||
if (logType.Equals("trace", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var loginUsers = TraceHelper.RetrieveAll(null, null, null);
|
||||
var temp = loginUsers.GroupBy(usr => usr.LogTime.ToString("yyyy-MM-dd"));
|
||||
var max = temp.Any() ? temp.Max(g => g.Count()) : 1;
|
||||
ret.Polylines = temp.Select((g, index) =>
|
||||
{
|
||||
ret.Datas.Add(new KeyValuePair<string, string>(g.Key, g.Count().ToString()));
|
||||
return $"{index * 5},{Math.Round(g.Count() * 28.0 / max, 2)}";
|
||||
});
|
||||
}
|
||||
if (logType.Equals("log", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var loginUsers = LogHelper.RetrieveAll(null, null, null);
|
||||
var temp = loginUsers.GroupBy(usr => usr.LogTime.ToString("yyyy-MM-dd"));
|
||||
var max = temp.Any() ? temp.Max(g => g.Count()) : 1;
|
||||
ret.Polylines = temp.Select((g, index) =>
|
||||
{
|
||||
ret.Datas.Add(new KeyValuePair<string, string>(g.Key, g.Count().ToString()));
|
||||
return $"{index * 5},{Math.Round(g.Count() * 28.0 / max, 2)}";
|
||||
});
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class AnalyseData
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public IEnumerable<string> Polylines { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public List<KeyValuePair<string, string>> Datas { get; set; } = new List<KeyValuePair<string, string>>();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -30,7 +30,7 @@ namespace Bootstrap.Admin.Query
|
|||
/// <returns></returns>
|
||||
public QueryData<Log> RetrieveData()
|
||||
{
|
||||
var data = LogHelper.Retrieves(this, OperateTimeStart, OperateTimeEnd, OperateType);
|
||||
var data = LogHelper.RetrievePages(this, OperateTimeStart, OperateTimeEnd, OperateType);
|
||||
var ret = new QueryData<Log>();
|
||||
ret.total = data.TotalItems;
|
||||
ret.rows = data.Items;
|
||||
|
|
|
@ -30,6 +30,7 @@ namespace Bootstrap.Admin.Query
|
|||
/// <returns></returns>
|
||||
public QueryData<LoginUser> RetrieveData()
|
||||
{
|
||||
if (string.IsNullOrEmpty(Order)) Order = "LoginTime desc";
|
||||
var data = LoginHelper.RetrievePages(this, StartTime, EndTime, LoginIP);
|
||||
return new QueryData<LoginUser>
|
||||
{
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
@model NavigatorBarModel
|
||||
@{
|
||||
ViewBag.Title = "网站分析";
|
||||
}
|
||||
@section css {
|
||||
<environment include="Development">
|
||||
<link href="~/lib/datetimepicker/css//bootstrap-datetimepicker.css" rel="stylesheet" />
|
||||
<link href="~/lib/bootstrap-table/bootstrap-table.css" rel="stylesheet" />
|
||||
</environment>
|
||||
<environment exclude="Development">
|
||||
<link href="~/lib/datetimepicker/css//bootstrap-datetimepicker.min.css" rel="stylesheet" />
|
||||
<link href="~/lib/bootstrap-table/bootstrap-table.min.css" rel="stylesheet" />
|
||||
</environment>
|
||||
<style>
|
||||
.card .card-body {
|
||||
padding-bottom: 15px;
|
||||
}
|
||||
|
||||
.spark {
|
||||
position: absolute;
|
||||
}
|
||||
</style>
|
||||
}
|
||||
@section javascript {
|
||||
<environment include="Development">
|
||||
<script src="~/lib/bootstrap-table/bootstrap-table.js"></script>
|
||||
<script src="~/lib/bootstrap-table/locale/bootstrap-table-zh-CN.js"></script>
|
||||
<script src="~/lib/datetimepicker/js/bootstrap-datetimepicker.js"></script>
|
||||
<script src="~/lib/echart/echarts-all.js"></script>
|
||||
</environment>
|
||||
<environment exclude="Development">
|
||||
<script src="~/lib/bootstrap-table/bootstrap-table.min.js"></script>
|
||||
<script src="~/lib/bootstrap-table/locale/bootstrap-table-zh-CN.min.js"></script>
|
||||
<script src="~/lib/datetimepicker/js/bootstrap-datetimepicker.min.js"></script>
|
||||
<script src="~/lib/echart/echarts-all.min.js"></script>
|
||||
</environment>
|
||||
<script src="~/lib/datetimepicker/js/locales/bootstrap-datetimepicker.zh-CN.js"></script>
|
||||
<script src="~/js/analyse.js" asp-append-version="true"></script>
|
||||
}
|
||||
<div class="card d-none">
|
||||
<div class="card-header">查询条件</div>
|
||||
<div class="card-body">
|
||||
<form class="form-inline">
|
||||
<div class="row">
|
||||
<div class="form-group col-sm-auto">
|
||||
<label class="control-label" for="txt_operate_start">起始时间</label>
|
||||
<div class="input-group date">
|
||||
<input id="txt_operate_start" class="form-control" size="16" type="text" value="@DateTime.Today.ToString("yyyy-MM-dd")" readonly>
|
||||
<div class="input-group-append input-group-addon">
|
||||
<div class="input-group-text"><span class="fa fa-times"></span></div>
|
||||
</div>
|
||||
<div class="input-group-append input-group-addon">
|
||||
<div class="input-group-text"><span class="fa fa-calendar"></span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group col-sm-auto">
|
||||
<label class="control-label" for="txt_operate_end">终止时间</label>
|
||||
<div class="input-group date">
|
||||
<input id="txt_operate_end" class="form-control" size="16" type="text" value="@DateTime.Today.ToString("yyyy-MM-dd")" readonly>
|
||||
<div class="input-group-append input-group-addon">
|
||||
<div class="input-group-text"><span class="fa fa-times"></span></div>
|
||||
</div>
|
||||
<div class="input-group-append input-group-addon">
|
||||
<div class="input-group-text"><span class="fa fa-calendar"></span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group col-sm-auto">
|
||||
<label class="control-label" for="txt_ip">请求IP</label>
|
||||
<input type="text" class="form-control" id="txt_ip" />
|
||||
</div>
|
||||
<div class="form-group col-sm-auto flex-md-fill justify-content-md-end">
|
||||
<button type="button" id="btn_query" class="btn btn-primary btn-fill"><i class="fa fa-search" aria-hidden="true"></i><span>查询</span></button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
操作日志
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div id="log" class="spark"></div>
|
||||
<div id="logChart" style="height: 200px"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
登录日志
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div id="login" class="spark"></div>
|
||||
<div id="loginChart" style="height: 200px"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
访问日志
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div id="trace" class="spark"></div>
|
||||
<div id="traceChart" style="height: 200px"></div>
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,219 @@
|
|||
(function ($) {
|
||||
// sparkline component
|
||||
'use strict';
|
||||
|
||||
var lgbSparkline = function (element, options) {
|
||||
this.$element = $(element);
|
||||
this.options = $.extend({}, lgbSparkline.DEFAULTS, options);
|
||||
this.init();
|
||||
};
|
||||
|
||||
lgbSparkline.VERSION = '1.0';
|
||||
lgbSparkline.Author = 'argo@163.com';
|
||||
lgbSparkline.DataKey = "lgb.sparkline";
|
||||
lgbSparkline.Template = '<span class="d-inline-block tooltipped tooltipped-s" aria-label="Past year of activity">';
|
||||
lgbSparkline.Template += '<svg width="155" height="30">';
|
||||
lgbSparkline.Template += ' <defs>';
|
||||
lgbSparkline.Template += ' <linearGradient id="{0}" x1="0" x2="0" y1="1" y2="0">';
|
||||
lgbSparkline.Template += ' <stop offset="10%" stop-color="#c6e48b"></stop>';
|
||||
lgbSparkline.Template += ' <stop offset="33%" stop-color="#7bc96f"></stop>';
|
||||
lgbSparkline.Template += ' <stop offset="66%" stop-color="#239a3b"></stop>';
|
||||
lgbSparkline.Template += ' <stop offset="90%" stop-color="#196127"></stop>';
|
||||
lgbSparkline.Template += ' </linearGradient>';
|
||||
lgbSparkline.Template += ' <mask id="{1}" x="0" y="0" width="155" height="28">';
|
||||
lgbSparkline.Template += ' <polyline transform="translate(0, 28) scale(1,-1)" points="" fill="transparent" stroke="#8cc665" stroke-width="2">';
|
||||
lgbSparkline.Template += ' </polyline>';
|
||||
lgbSparkline.Template += ' </mask>';
|
||||
lgbSparkline.Template += ' </defs>';
|
||||
lgbSparkline.Template += ' <g transform="translate(0, 2.0)">';
|
||||
lgbSparkline.Template += ' <rect x="0" y="-2" width="155" height="30" style="stroke: none; fill: url(#{0}); mask: url(#{1})"></rect>';
|
||||
lgbSparkline.Template += ' </g>';
|
||||
lgbSparkline.Template += '</svg>';
|
||||
lgbSparkline.Template += '</span>';
|
||||
|
||||
lgbSparkline.AllowMethods = /val/;
|
||||
|
||||
function Plugin(option) {
|
||||
var params = $.makeArray(arguments).slice(1);
|
||||
return this.each(function () {
|
||||
var $this = $(this);
|
||||
var data = $this.data(lgbSparkline.DataKey);
|
||||
var options = typeof option === 'object' && option;
|
||||
|
||||
if (!data) $this.data(lgbSparkline.DataKey, data = new lgbSparkline(this, options));
|
||||
if (!lgbSparkline.AllowMethods.test(option)) return;
|
||||
if (typeof option === 'string') {
|
||||
data[option].apply(data, params);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$.fn.lgbSparkline = Plugin;
|
||||
$.fn.lgbSparkline.Constructor = lgbSparkline;
|
||||
|
||||
var _proto = lgbSparkline.prototype;
|
||||
_proto.init = function () {
|
||||
var getUID = function (prefix) {
|
||||
if (!prefix) prefix = 'lgb';
|
||||
do prefix += ~~(Math.random() * 1000000);
|
||||
while (document.getElementById(prefix));
|
||||
return prefix;
|
||||
};
|
||||
|
||||
var that = this;
|
||||
var element = $.format(lgbSparkline.Template, getUID('gradient'), getUID('spark'))
|
||||
this.$ctl = $(element).appendTo(this.$element);
|
||||
};
|
||||
_proto.val = function (val) {
|
||||
this.$ctl.find('polyline').attr('points', val);
|
||||
};
|
||||
})(jQuery);
|
||||
|
||||
$(function () {
|
||||
$.bc({
|
||||
url: "api/Analyse?logType=LoginUsers",
|
||||
callback: function (result) {
|
||||
console.log(result);
|
||||
$('#login').lgbSparkline('val', result.Polylines.join(' '));
|
||||
var op = $.extend(true, {}, option, {
|
||||
legend: { data: ["登录数量"] },
|
||||
series: [
|
||||
{
|
||||
name: "登录数量",
|
||||
data: result.Datas.map(function (val, index) {
|
||||
return val.Value;
|
||||
})
|
||||
}
|
||||
],
|
||||
xAxis: [
|
||||
{
|
||||
data: result.Datas.map(function (val, index) {
|
||||
return val.Key;
|
||||
})
|
||||
}
|
||||
],
|
||||
dataZoom: {
|
||||
start: 50
|
||||
}
|
||||
});
|
||||
var loginChart = echarts.init(document.getElementById('loginChart'));
|
||||
loginChart.setOption(op);
|
||||
}
|
||||
});
|
||||
$.bc({
|
||||
url: "api/Analyse?logType=log",
|
||||
callback: function (result) {
|
||||
console.log(result);
|
||||
$('#log').lgbSparkline('val', result.Polylines.join(' '));
|
||||
var op = $.extend(true, {}, option, {
|
||||
legend: { data: ["操作数量"] },
|
||||
series: [
|
||||
{
|
||||
name: "操作数量",
|
||||
data: result.Datas.map(function (val, index) {
|
||||
return val.Value;
|
||||
})
|
||||
}
|
||||
],
|
||||
xAxis: [
|
||||
{
|
||||
data: result.Datas.map(function (val, index) {
|
||||
return val.Key;
|
||||
})
|
||||
}
|
||||
]
|
||||
});
|
||||
var logChart = echarts.init(document.getElementById('logChart'));
|
||||
logChart.setOption(op);
|
||||
}
|
||||
});
|
||||
$.bc({
|
||||
url: "api/Analyse?logType=trace",
|
||||
callback: function (result) {
|
||||
console.log(result);
|
||||
$('#trace').lgbSparkline('val', result.Polylines.join(' '));
|
||||
var op = $.extend(true, {}, option, {
|
||||
legend: { data: ["访问数量"] },
|
||||
series: [
|
||||
{
|
||||
name: "访问数量",
|
||||
data: result.Datas.map(function (val, index) {
|
||||
return val.Value;
|
||||
})
|
||||
}
|
||||
],
|
||||
xAxis: [
|
||||
{
|
||||
data: result.Datas.map(function (val, index) {
|
||||
return val.Key;
|
||||
})
|
||||
}
|
||||
]
|
||||
});
|
||||
var traceChart = echarts.init(document.getElementById('traceChart'));
|
||||
traceChart.setOption(op);
|
||||
}
|
||||
});
|
||||
|
||||
var option = {
|
||||
title: {
|
||||
text: '',
|
||||
subtext: ''
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis'
|
||||
},
|
||||
legend: {
|
||||
data: ['日访问量']
|
||||
},
|
||||
toolbox: {
|
||||
show: true,
|
||||
feature: {
|
||||
mark: { show: true },
|
||||
dataZoom: { show: true },
|
||||
dataView: { show: false },
|
||||
magicType: { show: true, type: ['line', 'bar'] },
|
||||
restore: { show: true },
|
||||
saveAsImage: { show: true }
|
||||
}
|
||||
},
|
||||
calculable: true,
|
||||
dataZoom: {
|
||||
show: true,
|
||||
realtime: true,
|
||||
start: 0,
|
||||
end: 100
|
||||
},
|
||||
xAxis: [
|
||||
{
|
||||
type: 'category',
|
||||
boundaryGap: false,
|
||||
data: function () {
|
||||
var list = [];
|
||||
for (var i = 1; i <= 30; i++) {
|
||||
list.push('2013-03-' + i);
|
||||
}
|
||||
return list;
|
||||
}()
|
||||
}
|
||||
],
|
||||
yAxis: [
|
||||
{
|
||||
type: 'value'
|
||||
}
|
||||
],
|
||||
series: [
|
||||
{
|
||||
name: '日访问量',
|
||||
type: 'line',
|
||||
data: function () {
|
||||
var list = [];
|
||||
for (var i = 1; i <= 30; i++) {
|
||||
list.push(Math.round(Math.random() * 30));
|
||||
}
|
||||
return list;
|
||||
}()
|
||||
}
|
||||
]
|
||||
};
|
||||
});
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
|
@ -2,6 +2,7 @@
|
|||
using MongoDB.Driver;
|
||||
using PetaPoco;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Bootstrap.DataAccess.MongoDB
|
||||
|
@ -19,7 +20,7 @@ namespace Bootstrap.DataAccess.MongoDB
|
|||
/// <param name="endTime"></param>
|
||||
/// <param name="opType"></param>
|
||||
/// <returns></returns>
|
||||
public override Page<DataAccess.Log> Retrieves(PaginationOption po, DateTime? startTime, DateTime? endTime, string opType)
|
||||
public override Page<DataAccess.Log> RetrievePages(PaginationOption po, DateTime? startTime, DateTime? endTime, string opType)
|
||||
{
|
||||
var filterBuilder = Builders<DataAccess.Log>.Filter;
|
||||
var filter = filterBuilder.Empty;
|
||||
|
@ -62,6 +63,26 @@ namespace Bootstrap.DataAccess.MongoDB
|
|||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="startTime"></param>
|
||||
/// <param name="endTime"></param>
|
||||
/// <param name="opType"></param>
|
||||
/// <returns></returns>
|
||||
public override IEnumerable<DataAccess.Log> RetrieveAll(DateTime? startTime, DateTime? endTime, string opType)
|
||||
{
|
||||
var filterBuilder = Builders<DataAccess.Log>.Filter;
|
||||
var filter = filterBuilder.Empty;
|
||||
if (startTime.HasValue) filter = filterBuilder.Gte("LogTime", startTime.Value);
|
||||
if (endTime.HasValue) filter = filterBuilder.Lt("LogTime", endTime.Value.AddDays(1).AddSeconds(-1));
|
||||
if (!string.IsNullOrEmpty(opType)) filter = filterBuilder.Eq("CRUD", opType);
|
||||
|
||||
// sort
|
||||
var sort = Builders<DataAccess.Log>.Sort.Ascending(t => t.LogTime);
|
||||
return DbManager.Logs.Find(filter).Sort(sort).ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除日志信息
|
||||
/// </summary>
|
||||
|
|
|
@ -30,7 +30,7 @@ namespace Bootstrap.DataAccess.MongoDB
|
|||
/// <returns></returns>
|
||||
public override Page<DataAccess.LoginUser> RetrieveByPages(PaginationOption po, DateTime? startTime, DateTime? endTime, string ip)
|
||||
{
|
||||
var logs = Retrieves(startTime, endTime, ip);
|
||||
var logs = RetrieveAll(startTime, endTime, ip);
|
||||
return new Page<DataAccess.LoginUser>()
|
||||
{
|
||||
Context = logs,
|
||||
|
@ -46,7 +46,7 @@ namespace Bootstrap.DataAccess.MongoDB
|
|||
/// 获取所有登录数据
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override IEnumerable<DataAccess.LoginUser> Retrieves(DateTime? startTime, DateTime? endTime, string ip)
|
||||
public override IEnumerable<DataAccess.LoginUser> RetrieveAll(DateTime? startTime, DateTime? endTime, string ip)
|
||||
{
|
||||
var filterBuilder = Builders<DataAccess.LoginUser>.Filter;
|
||||
var filter = filterBuilder.Empty;
|
||||
|
@ -56,7 +56,7 @@ namespace Bootstrap.DataAccess.MongoDB
|
|||
|
||||
return DbManager.LoginUsers
|
||||
.Find(filter)
|
||||
.Sort(Builders<DataAccess.LoginUser>.Sort.Descending(t => t.LoginTime)).ToList();
|
||||
.Sort(Builders<DataAccess.LoginUser>.Sort.Ascending(t => t.LoginTime)).ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ using Longbow.Web.Mvc;
|
|||
using MongoDB.Driver;
|
||||
using PetaPoco;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Bootstrap.DataAccess.MongoDB
|
||||
|
@ -15,7 +16,7 @@ namespace Bootstrap.DataAccess.MongoDB
|
|||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override Page<DataAccess.Trace> Retrieves(PaginationOption po, DateTime? startTime, DateTime? endTime, string ip)
|
||||
public override Page<DataAccess.Trace> RetrievePages(PaginationOption po, DateTime? startTime, DateTime? endTime, string ip)
|
||||
{
|
||||
// filter
|
||||
var filterBuilder = Builders<DataAccess.Trace>.Filter;
|
||||
|
@ -65,6 +66,26 @@ namespace Bootstrap.DataAccess.MongoDB
|
|||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="startTime"></param>
|
||||
/// <param name="endTime"></param>
|
||||
/// <param name="ip"></param>
|
||||
/// <returns></returns>
|
||||
public override IEnumerable<DataAccess.Trace> RetrieveAll(DateTime? startTime, DateTime? endTime, string ip)
|
||||
{
|
||||
var filterBuilder = Builders<DataAccess.Trace>.Filter;
|
||||
var filter = filterBuilder.Empty;
|
||||
if (startTime.HasValue) filter = filterBuilder.Gt("LogTime", startTime.Value);
|
||||
if (endTime.HasValue) filter = filterBuilder.Lt("LogTime", endTime.Value.AddDays(1).AddSeconds(-1));
|
||||
if (!string.IsNullOrEmpty(ip)) filter = filterBuilder.Eq("Ip", ip);
|
||||
|
||||
// sort
|
||||
var sort = Builders<DataAccess.Trace>.Sort.Ascending(t => t.LogTime);
|
||||
return DbManager.Traces.Find(filter).Sort(sort).ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
using Longbow.Web.Mvc;
|
||||
using PetaPoco;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Bootstrap.DataAccess
|
||||
{
|
||||
|
@ -15,7 +16,13 @@ namespace Bootstrap.DataAccess
|
|||
/// </summary>
|
||||
/// <param name="op"></param>
|
||||
/// <returns></returns>
|
||||
public static Page<Log> Retrieves(PaginationOption op, DateTime? startTime, DateTime? endTime, string opType) => DbContextManager.Create<Log>().Retrieves(op, startTime, endTime, opType);
|
||||
public static Page<Log> RetrievePages(PaginationOption op, DateTime? startTime, DateTime? endTime, string opType) => DbContextManager.Create<Log>().RetrievePages(op, startTime, endTime, opType);
|
||||
|
||||
/// <summary>
|
||||
/// 查询所有日志信息
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<Log> RetrieveAll(DateTime? startTime, DateTime? endTime, string opType) => DbContextManager.Create<Log>().RetrieveAll(startTime, endTime, opType);
|
||||
|
||||
/// <summary>
|
||||
/// 保存新增的日志信息
|
||||
|
|
|
@ -40,7 +40,7 @@ namespace Bootstrap.DataAccess
|
|||
/// <returns></returns>
|
||||
public static IEnumerable<LoginUser> RetrieveAll(DateTime? startTime, DateTime? endTime, string ip)
|
||||
{
|
||||
return DbContextManager.Create<LoginUser>().Retrieves(startTime, endTime, ip);
|
||||
return DbContextManager.Create<LoginUser>().RetrieveAll(startTime, endTime, ip);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ using Longbow.Web.Mvc;
|
|||
using Microsoft.AspNetCore.Http;
|
||||
using PetaPoco;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Bootstrap.DataAccess
|
||||
{
|
||||
|
@ -44,6 +45,15 @@ namespace Bootstrap.DataAccess
|
|||
/// <param name="endTime"></param>
|
||||
/// <param name="ip"></param>
|
||||
/// <returns></returns>
|
||||
public static Page<Trace> Retrieves(PaginationOption po, DateTime? startTime, DateTime? endTime, string ip) => DbContextManager.Create<Trace>().Retrieves(po, startTime, endTime, ip);
|
||||
public static Page<Trace> Retrieves(PaginationOption po, DateTime? startTime, DateTime? endTime, string ip) => DbContextManager.Create<Trace>().RetrievePages(po, startTime, endTime, ip);
|
||||
|
||||
/// <summary>
|
||||
/// 获得指定IP历史访问记录
|
||||
/// </summary>
|
||||
/// <param name="startTime"></param>
|
||||
/// <param name="endTime"></param>
|
||||
/// <param name="ip"></param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<Trace> RetrieveAll(DateTime? startTime, DateTime? endTime, string ip) => DbContextManager.Create<Trace>().RetrieveAll(startTime, endTime, ip);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using Longbow.Web.Mvc;
|
||||
using PetaPoco;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Bootstrap.DataAccess
|
||||
{
|
||||
|
@ -28,18 +29,36 @@ namespace Bootstrap.DataAccess
|
|||
/// <param name="endTime"></param>
|
||||
/// <param name="opType"></param>
|
||||
/// <returns></returns>
|
||||
public virtual new Page<Log> Retrieves(PaginationOption po, DateTime? startTime, DateTime? endTime, string opType)
|
||||
public virtual new Page<Log> RetrievePages(PaginationOption po, DateTime? startTime, DateTime? endTime, string opType)
|
||||
{
|
||||
var sql = new Sql("select CRUD, UserName, LogTime, Ip, Browser, OS, City, RequestUrl, RequestData from Logs");
|
||||
if (startTime.HasValue) sql.Append("where LogTime >= @0", startTime.Value);
|
||||
if (endTime.HasValue) sql.Append("where LogTime < @0", endTime.Value.AddDays(1).AddSeconds(-1));
|
||||
if (startTime == null && endTime == null) sql.Append("where LogTime > @0", DateTime.Today.AddMonths(0 - DictHelper.RetrieveExceptionsLogPeriod()));
|
||||
if (!string.IsNullOrEmpty(opType)) sql.Append("where CRUD = @0", opType);
|
||||
sql.Append($"order by {po.Sort} {po.Order}");
|
||||
if (startTime.HasValue) sql.Where("LogTime >= @0", startTime.Value);
|
||||
if (endTime.HasValue) sql.Where("LogTime < @0", endTime.Value.AddDays(1).AddSeconds(-1));
|
||||
if (startTime == null && endTime == null) sql.Where("LogTime > @0", DateTime.Today.AddMonths(0 - DictHelper.RetrieveExceptionsLogPeriod()));
|
||||
if (!string.IsNullOrEmpty(opType)) sql.Where("CRUD = @0", opType);
|
||||
sql.OrderBy($"{po.Sort} {po.Order}");
|
||||
|
||||
return DbManager.Create().Page<Log>(po.PageIndex, po.Limit, sql);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="startTime"></param>
|
||||
/// <param name="endTime"></param>
|
||||
/// <param name="opType"></param>
|
||||
/// <returns></returns>
|
||||
public virtual new IEnumerable<Log> RetrieveAll(DateTime? startTime, DateTime? endTime, string opType)
|
||||
{
|
||||
var sql = new Sql("select CRUD, UserName, LogTime, Ip, Browser, OS, City, RequestUrl, RequestData from Logs");
|
||||
if (startTime.HasValue) sql.Where("LogTime >= @0", startTime.Value);
|
||||
if (endTime.HasValue) sql.Where("LogTime < @0", endTime.Value.AddDays(1).AddSeconds(-1));
|
||||
if (!string.IsNullOrEmpty(opType)) sql.Where("CRUD = @0", opType);
|
||||
sql.OrderBy("LogTime");
|
||||
|
||||
return DbManager.Create().Fetch<Log>(sql);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除日志信息
|
||||
/// </summary>
|
||||
|
|
|
@ -90,6 +90,14 @@ namespace Bootstrap.DataAccess
|
|||
/// 获取所有登录数据
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public virtual IEnumerable<LoginUser> Retrieves(DateTime? startTime, DateTime? endTime, string ip) => DbManager.Create().Fetch<LoginUser>();
|
||||
public virtual IEnumerable<LoginUser> RetrieveAll(DateTime? startTime, DateTime? endTime, string ip)
|
||||
{
|
||||
var sql = new Sql("select UserName, LoginTime, Ip, Browser, OS, City, Result from LoginLogs");
|
||||
if (startTime.HasValue) sql.Where("LoginTime >= @0", startTime.Value);
|
||||
if (endTime.HasValue) sql.Where("LoginTime < @0", endTime.Value.AddDays(1));
|
||||
if (!string.IsNullOrEmpty(ip)) sql.Where("ip = @0", ip);
|
||||
sql.OrderBy($"LoginTime");
|
||||
return DbManager.Create().Fetch<LoginUser>(sql);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using Longbow.Web.Mvc;
|
||||
using PetaPoco;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Bootstrap.DataAccess
|
||||
{
|
||||
|
@ -75,7 +76,7 @@ namespace Bootstrap.DataAccess
|
|||
/// <param name="endTime"></param>
|
||||
/// <param name="ip"></param>
|
||||
/// <returns></returns>
|
||||
public virtual Page<Trace> Retrieves(PaginationOption po, DateTime? startTime, DateTime? endTime, string ip)
|
||||
public virtual Page<Trace> RetrievePages(PaginationOption po, DateTime? startTime, DateTime? endTime, string ip)
|
||||
{
|
||||
var sql = new Sql("select UserName, LogTime, IP, Browser, OS, City, RequestUrl from Traces");
|
||||
if (startTime.HasValue) sql.Where("LogTime > @0", startTime.Value);
|
||||
|
@ -87,6 +88,24 @@ namespace Bootstrap.DataAccess
|
|||
return DbManager.Create().Page<Trace>(po.PageIndex, po.Limit, sql);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="startTime"></param>
|
||||
/// <param name="endTime"></param>
|
||||
/// <param name="ip"></param>
|
||||
/// <returns></returns>
|
||||
public virtual IEnumerable<Trace> RetrieveAll(DateTime? startTime, DateTime? endTime, string ip)
|
||||
{
|
||||
var sql = new Sql("select UserName, LogTime, IP, Browser, OS, City, RequestUrl from Traces");
|
||||
if (startTime.HasValue) sql.Where("LogTime > @0", startTime.Value);
|
||||
if (endTime.HasValue) sql.Where("LogTime < @0", endTime.Value.AddDays(1).AddSeconds(-1));
|
||||
if (!string.IsNullOrEmpty(ip)) sql.Where("IP = @0", ip);
|
||||
sql.OrderBy("LogTime");
|
||||
|
||||
return DbManager.Create().Fetch<Trace>(sql);
|
||||
}
|
||||
|
||||
private static void ClearTraces() => System.Threading.Tasks.Task.Run(() =>
|
||||
{
|
||||
DbManager.Create().Execute("delete from Traces where LogTime < @0", DateTime.Now.AddMonths(0 - DictHelper.RetrieveAccessLogPeriod()));
|
||||
|
|
|
@ -623,6 +623,18 @@
|
|||
"IsResource": NumberInt(0),
|
||||
"Application": "0"
|
||||
},
|
||||
{
|
||||
"_id": ObjectId("5bd7b8445fa31256f77e4b90"),
|
||||
"ParentId": "0",
|
||||
"Name": "网站分析",
|
||||
"Order": NumberInt(145),
|
||||
"Icon": "fa fa-line-chart",
|
||||
"Url": "~/Admin/Analyse",
|
||||
"Category": "0",
|
||||
"Target": "_self",
|
||||
"IsResource": NumberInt(0),
|
||||
"Application": "0"
|
||||
},
|
||||
{
|
||||
"_id": ObjectId("5bd7b8445fa31256f77e4b9d"),
|
||||
"ParentId": "0",
|
||||
|
|
|
@ -98,6 +98,7 @@ INSERT INTO Navigations (ParentId, Name, `Order`, Icon, Url, Category) VALUES (@
|
|||
INSERT INTO Navigations (ParentId, Name, `Order`, Icon, Url, Category) VALUES (@@identity - 1, '登录日志', 20, 'fa fa-user-circle-o', '~/Admin/Logins', '0');
|
||||
INSERT INTO Navigations (ParentId, Name, `Order`, Icon, Url, Category) VALUES (@@identity - 2, '访问日志', 30, 'fa fa-bars', '~/Admin/Traces', '0');
|
||||
INSERT INTO Navigations (ParentId, Name, `Order`, Icon, Url, Category) VALUES (0, '在线用户', 140, 'fa fa-users', '~/Admin/Online', '0');
|
||||
INSERT INTO Navigations (ParentId, Name, `Order`, Icon, Url, Category) VALUES (0, '网站分析', 145, 'fa fa-line-chart', '~/Admin/Analyse', '0');
|
||||
INSERT INTO Navigations (ParentId, Name, `Order`, Icon, Url, Category) VALUES (0, '程序异常', 150, 'fa fa-cubes', '~/Admin/Exceptions', '0');
|
||||
INSERT INTO Navigations (ParentId, Name, `Order`, Icon, Url, Category, IsResource) VALUES (@@identity, '服务器日志', 10, 'fa fa-fa', 'log', '0', 2);
|
||||
INSERT INTO Navigations (ParentId, Name, `Order`, Icon, Url, Category) VALUES (0, '工具集合', 160, 'fa fa-gavel', '#', '0');
|
||||
|
|
|
@ -98,6 +98,7 @@ INSERT INTO Navigations (ParentId, Name, "order", Icon, Url, Category) VALUES (c
|
|||
INSERT INTO Navigations (ParentId, Name, "order", Icon, Url, Category) VALUES (currval('navigations_id_seq') - 2, 0, '登录日志', 20, 'fa fa-user-circle-o', '~/Admin/Logins', '0');
|
||||
INSERT INTO Navigations (ParentId, Name, "order", Icon, Url, Category) VALUES (currval('navigations_id_seq') - 3, 0, '访问日志', 30, 'fa fa-bars', '~/Admin/Traces', '0');
|
||||
INSERT INTO Navigations (ParentId, Name, "order", Icon, Url, Category) VALUES (0, '在线用户', 140, 'fa fa-users', '~/Admin/Online', '0');
|
||||
INSERT INTO Navigations (ParentId, Name, "order", Icon, Url, Category) VALUES (0, '网站分析', 145, 'fa fa-line-chart', '~/Admin/Analyse', '0');
|
||||
INSERT INTO Navigations (ParentId, Name, "order", Icon, Url, Category) VALUES (0, '程序异常', 150, 'fa fa-cubes', '~/Admin/Exceptions', '0');
|
||||
INSERT INTO [Navigations] ([ParentId], [Name], [Order], [Icon], [Url], [Category], IsResource) VALUES (currval('navigations_id_seq') - 1, '服务器日志', 10, 'fa fa-fa', 'log', '0', 2);
|
||||
INSERT INTO Navigations (ParentId, Name, "order", Icon, Url, Category) VALUES (0, '工具集合', 160, 'fa fa-gavel', '#', '0');
|
||||
|
|
|
@ -98,6 +98,7 @@ INSERT INTO [Navigations] ([ParentId], [Name], [Order], [Icon], [Url], [Category
|
|||
INSERT INTO [Navigations] ([ParentId], [Name], [Order], [Icon], [Url], [Category]) VALUES (last_insert_rowid() - 1, '登录日志', 20, 'fa fa-user-circle-o', '~/Admin/Logins', '0');
|
||||
INSERT INTO [Navigations] ([ParentId], [Name], [Order], [Icon], [Url], [Category]) VALUES (last_insert_rowid() - 2, '访问日志', 30, 'fa fa-bars', '~/Admin/Traces', '0');
|
||||
INSERT INTO [Navigations] ([ParentId], [Name], [Order], [Icon], [Url], [Category]) VALUES (0, '在线用户', 140, 'fa fa-users', '~/Admin/Online', '0');
|
||||
INSERT INTO [Navigations] ([ParentId], [Name], [Order], [Icon], [Url], [Category]) VALUES (0, '网站分析', 145, 'fa fa-line-chart', '~/Admin/Analyse', '0');
|
||||
INSERT INTO [Navigations] ([ParentId], [Name], [Order], [Icon], [Url], [Category]) VALUES (0, '程序异常', 150, 'fa fa-cubes', '~/Admin/Exceptions', '0');
|
||||
INSERT INTO [Navigations] ([ParentId], [Name], [Order], [Icon], [Url], [Category], IsResource) VALUES (last_insert_rowid(), '服务器日志', 10, 'fa fa-fa', 'log', '0', 2);
|
||||
INSERT INTO [Navigations] ([ParentId], [Name], [Order], [Icon], [Url], [Category]) VALUES (0, '工具集合', 160, 'fa fa-gavel', '#', '0');
|
||||
|
|
|
@ -101,6 +101,7 @@ INSERT [Navigations] ([ParentId], [Name], [Order], [Icon], [Url], [Category]) VA
|
|||
INSERT [Navigations] ([ParentId], [Name], [Order], [Icon], [Url], [Category]) VALUES (@@Identity - 1, N'登录日志', 20, N'fa fa-user-circle-o', N'~/Admin/Logins', N'0')
|
||||
INSERT [Navigations] ([ParentId], [Name], [Order], [Icon], [Url], [Category]) VALUES (@@Identity - 2, N'访问日志', 30, N'fa fa-bars', N'~/Admin/Traces', N'0')
|
||||
INSERT [Navigations] ([ParentId], [Name], [Order], [Icon], [Url], [Category]) VALUES (0, N'在线用户', 140, N'fa fa-users', N'~/Admin/Online', N'0')
|
||||
INSERT [Navigations] ([ParentId], [Name], [Order], [Icon], [Url], [Category]) VALUES (0, N'网站分析', 145, N'fa fa-line-chart', N'~/Admin/Analyse', N'0')
|
||||
INSERT [Navigations] ([ParentId], [Name], [Order], [Icon], [Url], [Category]) VALUES (0, N'程序异常', 150, N'fa fa-cubes', N'~/Admin/Exceptions', N'0')
|
||||
INSERT INTO [Navigations] ([ParentId], [Name], [Order], [Icon], [Url], [Category], IsResource) VALUES (@@Identity, N'服务器日志', 10, N'fa fa-fa', N'log', N'0', 2)
|
||||
INSERT [Navigations] ([ParentId], [Name], [Order], [Icon], [Url], [Category]) VALUES (0, N'工具集合', 160, N'fa fa-gavel', N'#', N'0')
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
using Xunit;
|
||||
using static Bootstrap.Admin.Controllers.Api.AnalyseController;
|
||||
|
||||
namespace Bootstrap.Admin.Api.SqlServer
|
||||
{
|
||||
public class AnalyseTest : ControllerTest
|
||||
{
|
||||
public AnalyseTest(BAWebHost factory) : base(factory, "api/Analyse") { }
|
||||
|
||||
[Fact]
|
||||
public async void Get_Ok()
|
||||
{
|
||||
var cates = await Client.GetAsJsonAsync<AnalyseData>("?logType=LoginUsers");
|
||||
Assert.NotNull(cates);
|
||||
cates = await Client.GetAsJsonAsync<AnalyseData>("?logType=log");
|
||||
Assert.NotNull(cates);
|
||||
cates = await Client.GetAsJsonAsync<AnalyseData>("?logType=trace");
|
||||
Assert.NotNull(cates);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -27,6 +27,7 @@ namespace Bootstrap.Admin.Controllers.SqlServer
|
|||
[InlineData("Online", "在线用户")]
|
||||
[InlineData("Tasks", "任务管理")]
|
||||
[InlineData("Mobile", "客户端测试")]
|
||||
[InlineData("Analyse", "网站分析")]
|
||||
public async void View_Ok(string view, string text)
|
||||
{
|
||||
var r = await Client.GetAsync(view);
|
||||
|
|
|
@ -36,11 +36,12 @@ namespace Bootstrap.DataAccess.SqlServer
|
|||
RequestUrl = "~/Home/Index"
|
||||
};
|
||||
LogHelper.Save(log);
|
||||
Assert.NotNull(LogHelper.Retrieves(new PaginationOption() { Limit = 20, Sort = "LogTime", Order = "desc" }, null, null, null));
|
||||
Assert.NotNull(LogHelper.Retrieves(new PaginationOption() { Limit = 20, Sort = "CRUD", Order = "desc" }, null, null, null));
|
||||
Assert.NotNull(LogHelper.Retrieves(new PaginationOption() { Limit = 20, Sort = "UserName", Order = "desc" }, null, null, null));
|
||||
Assert.NotNull(LogHelper.Retrieves(new PaginationOption() { Limit = 20, Sort = "Ip", Order = "desc" }, null, null, null));
|
||||
Assert.NotNull(LogHelper.Retrieves(new PaginationOption() { Limit = 20, Sort = "RequestUrl", Order = "desc" }, null, null, null));
|
||||
Assert.NotNull(LogHelper.RetrievePages(new PaginationOption() { Limit = 20, Sort = "LogTime", Order = "desc" }, null, null, null));
|
||||
Assert.NotNull(LogHelper.RetrievePages(new PaginationOption() { Limit = 20, Sort = "CRUD", Order = "desc" }, null, null, null));
|
||||
Assert.NotNull(LogHelper.RetrievePages(new PaginationOption() { Limit = 20, Sort = "UserName", Order = "desc" }, null, null, null));
|
||||
Assert.NotNull(LogHelper.RetrievePages(new PaginationOption() { Limit = 20, Sort = "Ip", Order = "desc" }, null, null, null));
|
||||
Assert.NotNull(LogHelper.RetrievePages(new PaginationOption() { Limit = 20, Sort = "RequestUrl", Order = "desc" }, null, null, null));
|
||||
Assert.NotEmpty(LogHelper.RetrieveAll(null, null, null));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,6 +45,7 @@ namespace Bootstrap.DataAccess.SqlServer
|
|||
Assert.NotEmpty(TraceHelper.Retrieves(new PaginationOption() { Limit = 20, Offset = 0, Order = "desc", Sort = "Browser" }, null, null, null).Items);
|
||||
Assert.NotEmpty(TraceHelper.Retrieves(new PaginationOption() { Limit = 20, Offset = 0, Order = "desc", Sort = "OS" }, null, null, null).Items);
|
||||
Assert.NotEmpty(TraceHelper.Retrieves(new PaginationOption() { Limit = 20, Offset = 0, Order = "desc", Sort = "RequestUrl" }, null, null, null).Items);
|
||||
Assert.NotEmpty(TraceHelper.RetrieveAll(null, null, null));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -175,7 +175,7 @@ namespace Bootstrap.DataAccess.SqlServer
|
|||
[Fact]
|
||||
public void RetrievePageLoginUsers_Ok()
|
||||
{
|
||||
var data = LoginHelper.RetrievePages(new PaginationOption() { Limit = 20, Offset = 0 }, null, null, "");
|
||||
var data = LoginHelper.RetrievePages(new PaginationOption() { Limit = 20, Offset = 0, Order = "LoginTime" }, null, null, "");
|
||||
Assert.NotNull(data.Items);
|
||||
}
|
||||
|
||||
|
|
Binary file not shown.
Loading…
Reference in New Issue