feat: 新增请求访问统计功能
This commit is contained in:
@@ -5,6 +5,7 @@ using Quartz;
|
|||||||
using Volo.Abp.BackgroundWorkers.Quartz;
|
using Volo.Abp.BackgroundWorkers.Quartz;
|
||||||
using Volo.Abp.Caching;
|
using Volo.Abp.Caching;
|
||||||
using Volo.Abp.DependencyInjection;
|
using Volo.Abp.DependencyInjection;
|
||||||
|
using Volo.Abp.Domain.Entities;
|
||||||
using Yi.Framework.Bbs.Domain.Entities;
|
using Yi.Framework.Bbs.Domain.Entities;
|
||||||
using Yi.Framework.Bbs.Domain.Shared.Caches;
|
using Yi.Framework.Bbs.Domain.Shared.Caches;
|
||||||
using Yi.Framework.Bbs.Domain.Shared.Enums;
|
using Yi.Framework.Bbs.Domain.Shared.Enums;
|
||||||
@@ -46,10 +47,13 @@ public class AccessLogStoreJob : QuartzBackgroundWorkerBase
|
|||||||
_repository = repository;
|
_repository = repository;
|
||||||
JobDetail = JobBuilder.Create<AccessLogStoreJob>().WithIdentity(nameof(AccessLogStoreJob))
|
JobDetail = JobBuilder.Create<AccessLogStoreJob>().WithIdentity(nameof(AccessLogStoreJob))
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
//每分钟执行一次
|
//每分钟执行一次
|
||||||
Trigger = TriggerBuilder.Create().WithIdentity(nameof(AccessLogStoreJob))
|
Trigger = TriggerBuilder.Create().WithIdentity(nameof(AccessLogStoreJob))
|
||||||
.WithCronSchedule("* * * * *")
|
.WithCronSchedule("0 * * * * ?")
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task Execute(IJobExecutionContext context)
|
public override async Task Execute(IJobExecutionContext context)
|
||||||
@@ -64,9 +68,20 @@ public class AccessLogStoreJob : QuartzBackgroundWorkerBase
|
|||||||
var entity = await _repository._DbQueryable.Where(x => x.AccessLogType == AccessLogTypeEnum.Request)
|
var entity = await _repository._DbQueryable.Where(x => x.AccessLogType == AccessLogTypeEnum.Request)
|
||||||
.Where(x => x.CreationTime.Date == DateTime.Today)
|
.Where(x => x.CreationTime.Date == DateTime.Today)
|
||||||
.FirstAsync();
|
.FirstAsync();
|
||||||
// _repository._Db.Storageable(list2).ExecuteCommandAsync();
|
|
||||||
|
|
||||||
|
|
||||||
|
if (entity is not null)
|
||||||
|
{
|
||||||
|
entity.Number = number+1;
|
||||||
|
await _repository.UpdateAsync(entity);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await _repository.InsertAsync((new AccessLogAggregateRoot() { Number = number,AccessLogType = AccessLogTypeEnum.Request}));
|
||||||
|
}
|
||||||
|
|
||||||
|
//删除前一天的缓存
|
||||||
|
await RedisClient.DelAsync($"{CacheKeyPrefix}:{AccessLogCacheConst.Key}:{DateTime.Now.Date.AddDays(-1)}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -55,9 +55,9 @@ namespace Yi.Framework.Bbs.Application.Services
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="AccessLogType"></param>
|
/// <param name="AccessLogType"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public async Task<List<AccessLogDto>> GetListAsync([FromQuery] AccessLogTypeEnum AccessLogType)
|
public async Task<List<AccessLogDto>> GetListAsync([FromQuery] AccessLogTypeEnum accessLogType)
|
||||||
{
|
{
|
||||||
var entities = await _repository._DbQueryable.Where(x => x.AccessLogType == AccessLogType)
|
var entities = await _repository._DbQueryable.Where(x => x.AccessLogType == accessLogType)
|
||||||
.Where(x => x.CreationTime >= DateTime.Now.AddMonths(-3))
|
.Where(x => x.CreationTime >= DateTime.Now.AddMonths(-3))
|
||||||
.OrderBy(x => x.CreationTime).ToListAsync();
|
.OrderBy(x => x.CreationTime).ToListAsync();
|
||||||
var output = entities.Adapt<List<AccessLogDto>>();
|
var output = entities.Adapt<List<AccessLogDto>>();
|
||||||
@@ -73,11 +73,11 @@ namespace Yi.Framework.Bbs.Application.Services
|
|||||||
public async Task AccessAsync()
|
public async Task AccessAsync()
|
||||||
{
|
{
|
||||||
//可判断http重复,防止同一ip多次访问
|
//可判断http重复,防止同一ip多次访问
|
||||||
var last = await _repository._DbQueryable.OrderByDescending(x => x.CreationTime).FirstAsync();
|
var last = await _repository._DbQueryable.Where(x=>x.AccessLogType==AccessLogTypeEnum.HomeClick).OrderByDescending(x => x.CreationTime).FirstAsync();
|
||||||
|
|
||||||
if (last is null || last.CreationTime.Date != DateTime.Today)
|
if (last is null || last.CreationTime.Date != DateTime.Today)
|
||||||
{
|
{
|
||||||
await _repository.InsertAsync(new AccessLogAggregateRoot());
|
await _repository.InsertAsync(new AccessLogAggregateRoot(){AccessLogType=AccessLogTypeEnum.HomeClick});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -90,10 +90,10 @@ namespace Yi.Framework.Bbs.Application.Services
|
|||||||
/// 获取当前周首页点击数据
|
/// 获取当前周首页点击数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public async Task<AccessLogDto[]> GetWeekAsync()
|
public async Task<AccessLogDto[]> GetWeekAsync([FromQuery] AccessLogTypeEnum accessLogType)
|
||||||
{
|
{
|
||||||
var lastSeven = await _repository._DbQueryable
|
var lastSeven = await _repository._DbQueryable
|
||||||
.Where(x => x.AccessLogType == AccessLogTypeEnum.HomeClick)
|
.Where(x => x.AccessLogType == accessLogType)
|
||||||
.OrderByDescending(x => x.CreationTime).ToPageListAsync(1, 7);
|
.OrderByDescending(x => x.CreationTime).ToPageListAsync(1, 7);
|
||||||
|
|
||||||
return WeekTimeHandler(lastSeven.ToArray());
|
return WeekTimeHandler(lastSeven.ToArray());
|
||||||
|
|||||||
@@ -288,8 +288,8 @@ namespace Yi.Abp.Web
|
|||||||
//swagger
|
//swagger
|
||||||
app.UseYiSwagger();
|
app.UseYiSwagger();
|
||||||
|
|
||||||
//流量访问统计,不启用
|
//流量访问统计,需redis支持,否则不生效
|
||||||
//app.UseAccessLog();
|
app.UseAccessLog();
|
||||||
|
|
||||||
//请求处理
|
//请求处理
|
||||||
app.UseYiApiHandlinge();
|
app.UseYiApiHandlinge();
|
||||||
|
|||||||
@@ -9,16 +9,18 @@ export function access() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 获取本周数据
|
// 获取本周数据
|
||||||
export function getWeek() {
|
export function getWeek(data) {
|
||||||
return request({
|
return request({
|
||||||
url: "/access-log/week",
|
url: "/access-log/week",
|
||||||
method: "get",
|
method: "get",
|
||||||
|
params :data
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// 获取全部数据
|
// 获取全部数据
|
||||||
export function getAccessList() {
|
export function getAccessList(data) {
|
||||||
return request({
|
return request({
|
||||||
url: "/access-log",
|
url: "/access-log",
|
||||||
method: "get",
|
method: "get",
|
||||||
|
params :data
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,7 +37,14 @@ const onClickText=()=>{
|
|||||||
.el-divider {
|
.el-divider {
|
||||||
margin: 0.2rem 0;
|
margin: 0.2rem 0;
|
||||||
}
|
}
|
||||||
|
.VisitsLineChart /deep/ .el-card__body{
|
||||||
|
padding: 0 20px;
|
||||||
|
}
|
||||||
|
.box-card-info {
|
||||||
|
width: 100%;
|
||||||
|
height: v-bind(height);
|
||||||
|
padding-bottom: 10px;
|
||||||
|
}
|
||||||
.card-header {
|
.card-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
@@ -52,9 +59,4 @@ const onClickText=()=>{
|
|||||||
margin: 1rem 0;
|
margin: 1rem 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.box-card {
|
|
||||||
width: 100%;
|
|
||||||
height: v-bind(height);
|
|
||||||
padding-bottom: 10px;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -3,7 +3,8 @@
|
|||||||
<el-row :gutter="20" class="top-div">
|
<el-row :gutter="20" class="top-div">
|
||||||
<el-col :span="17">
|
<el-col :span="17">
|
||||||
<div class="chat-hub">
|
<div class="chat-hub">
|
||||||
<p @click="onClickToChatHub">点击前往-最新上线<span>《聊天室》 </span>,现已支持<span>Ai助手</span>,希望能帮助大家</p>
|
<p @click="onClickToChatHub">点击前往-最新上线<span>《聊天室》 </span>,现已支持<span>Ai助手</span>,希望能帮助大家
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="scrollbar">
|
<div class="scrollbar">
|
||||||
<ScrollbarInfo/>
|
<ScrollbarInfo/>
|
||||||
@@ -97,23 +98,26 @@
|
|||||||
<el-col :span="24">
|
<el-col :span="24">
|
||||||
<InfoCard header="访问统计" class="VisitsLineChart" text="全站历史统计" @onClickText="onClickAccessLog">
|
<InfoCard header="访问统计" class="VisitsLineChart" text="全站历史统计" @onClickText="onClickAccessLog">
|
||||||
<template #content>
|
<template #content>
|
||||||
|
<p class="switch-span" @click="onClickWeekSwitch">切换</p>
|
||||||
<VisitsLineChart :option="statisOptions" class="statisChart"/>
|
<VisitsLineChart :option="statisOptions" class="statisChart"/>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
</InfoCard>
|
</InfoCard>
|
||||||
|
|
||||||
<el-dialog v-model="accessLogDialogVisible" title="全站历史统计" width="1200px" center>
|
<el-dialog v-model="accessLogDialogVisible" title="全站历史统计" width="1200px" center>
|
||||||
<el-tabs v-model="accessLogTab">
|
<el-tabs v-model="accessLogTab">
|
||||||
<el-tab-pane label="访问统计(近3月)" name="AccessLogChart" style="display: flex;justify-content: center;">
|
<el-tab-pane label="访问统计(近3月)" name="AccessLogChart"
|
||||||
|
style="display: flex;justify-content: center;">
|
||||||
<AccessLogChart :option="accessLogOptins" style="height: 600px;width: 1200px;"/>
|
<AccessLogChart :option="accessLogOptins" style="height: 600px;width: 1200px;"/>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
<el-tab-pane label="注册统计(近3月)" name="RegisterChart" style="display: flex;justify-content: center;">
|
<el-tab-pane label="注册统计(近3月)" name="RegisterChart"
|
||||||
|
style="display: flex;justify-content: center;">
|
||||||
<AccessLogChart :option="registerLogOptins" style="height: 600px;width: 1200px;"/>
|
<AccessLogChart :option="registerLogOptins" style="height: 600px;width: 1200px;"/>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
|
|
||||||
</el-tabs>
|
</el-tabs>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
|
||||||
@@ -129,7 +133,8 @@
|
|||||||
|
|
||||||
<el-col :span="24">
|
<el-col :span="24">
|
||||||
<template v-if="isPointFinished">
|
<template v-if="isPointFinished">
|
||||||
<InfoCard :items="pointList" header="财富排行榜" text="查看我的位置" height="400" @onClickText="onClickMoneyTop">
|
<InfoCard :items="pointList" header="财富排行榜" text="查看我的位置" height="400"
|
||||||
|
@onClickText="onClickMoneyTop">
|
||||||
<template #item="temp">
|
<template #item="temp">
|
||||||
<PointsRanking :pointsData="temp"/>
|
<PointsRanking :pointsData="temp"/>
|
||||||
</template>
|
</template>
|
||||||
@@ -256,6 +261,7 @@ const query = reactive({
|
|||||||
isTop: true,
|
isTop: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const weekQuery = reactive({accessLogType: "Request"});
|
||||||
//初始化
|
//初始化
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
access();
|
access();
|
||||||
@@ -266,7 +272,7 @@ onMounted(async () => {
|
|||||||
isDiscussFinished.value = discussConfig.isFinish;
|
isDiscussFinished.value = discussConfig.isFinish;
|
||||||
const {data: bannerData} = await bannerGetList();
|
const {data: bannerData} = await bannerGetList();
|
||||||
bannerList.value = bannerData.items;
|
bannerList.value = bannerData.items;
|
||||||
const { data: weekData } = await getWeek();
|
const {data: weekData} = await getWeek(weekQuery);
|
||||||
weekList.value = weekData;
|
weekList.value = weekData;
|
||||||
const {data: pointData, config: pointConfig} = await getRankingPoints();
|
const {data: pointData, config: pointConfig} = await getRankingPoints();
|
||||||
pointList.value = pointData.items;
|
pointList.value = pointData.items;
|
||||||
@@ -372,7 +378,7 @@ watch(
|
|||||||
async (value) => {
|
async (value) => {
|
||||||
switch (value) {
|
switch (value) {
|
||||||
case "AccessLogChart":
|
case "AccessLogChart":
|
||||||
const { data } = await getAccessList();
|
const {data} = await getAccessList(weekQuery);
|
||||||
accessAllList.value = data;
|
accessAllList.value = data;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -383,7 +389,6 @@ watch(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
)
|
)
|
||||||
const onClickAccessLog = async () => {
|
const onClickAccessLog = async () => {
|
||||||
accessLogDialogVisible.value = true;
|
accessLogDialogVisible.value = true;
|
||||||
@@ -391,6 +396,17 @@ const onClickAccessLog = async () => {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//切换统计开关
|
||||||
|
const onClickWeekSwitch = async () => {
|
||||||
|
if (weekQuery.accessLogType === "HomeClick") {
|
||||||
|
weekQuery.accessLogType= "Request";
|
||||||
|
} else if (weekQuery.accessLogType === "Request") {
|
||||||
|
weekQuery.accessLogType = "HomeClick";
|
||||||
|
}
|
||||||
|
|
||||||
|
const {data: weekData} = await getWeek(weekQuery);
|
||||||
|
weekList.value = weekData;
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.home-box {
|
.home-box {
|
||||||
@@ -539,6 +555,13 @@ const onClickAccessLog = async () => {
|
|||||||
padding: 0.5rem;
|
padding: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.VisitsLineChart p{
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
color: #409eff;
|
||||||
|
cursor: pointer;
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
.statisChart {
|
.statisChart {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 300px;
|
height: 300px;
|
||||||
@@ -550,6 +573,7 @@ const onClickAccessLog = async () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//走马灯,聊天室链接
|
//走马灯,聊天室链接
|
||||||
.chat-hub {
|
.chat-hub {
|
||||||
background-color: #E6A23C;
|
background-color: #E6A23C;
|
||||||
|
|||||||
Reference in New Issue
Block a user