feat: 新增全站历史统计功能

This commit is contained in:
陈淳
2024-02-27 13:43:56 +08:00
parent 5a2d9125d4
commit 6697649b97
7 changed files with 148 additions and 52 deletions

View File

@@ -44,6 +44,21 @@ namespace Yi.Framework.Bbs.Application.Services
} }
} }
/// <summary>
/// 获取全部访问流量
/// </summary>
/// <returns></returns>
public async Task<List<AccessLogDto>> Get()
{
var entities = await _repository._DbQueryable.OrderBy(x => x.CreationTime).ToListAsync();
var output = entities.Adapt<List<AccessLogDto>>();
output?.ForEach(x => x.CreationTime = x.CreationTime.Date);
return output;
}
/// <summary> /// <summary>
/// 触发 /// 触发
/// </summary> /// </summary>
@@ -106,5 +121,8 @@ namespace Yi.Framework.Bbs.Application.Services
return result.ToArray(); return result.ToArray();
} }
} }
} }

View File

@@ -93,5 +93,6 @@ namespace Yi.Framework.Bbs.Application.Services.Analyses
} }
} }
} }
} }

View File

@@ -15,3 +15,10 @@ export function getWeek() {
method: "get", method: "get",
}); });
} }
// 获取全部数据
export function getAccessList() {
return request({
url: "/access-log",
method: "get",
});
}

View File

@@ -2,7 +2,12 @@
import { ref } from "vue"; import { ref } from "vue";
const props = defineProps(["items", "header", "text", "hideDivider", "height"]); const props = defineProps(["items", "header", "text", "hideDivider", "height"]);
const emit = defineEmits(['onClickText'])
const height = ref(props.height + "px"); const height = ref(props.height + "px");
const onClickText=()=>{
emit('onClickText')
}
</script> </script>
<template> <template>
@@ -10,7 +15,7 @@ const height = ref(props.height + "px");
<template #header> <template #header>
<div class="card-header"> <div class="card-header">
<span>{{ props.header }}</span> <span>{{ props.header }}</span>
<el-link :underline="false" type="primary">{{ props.text }}</el-link> <el-link :underline="false" type="primary" @click="onClickText">{{ props.text }}</el-link>
</div> </div>
</template> </template>

View File

@@ -6,22 +6,11 @@
<ScrollbarInfo /> <ScrollbarInfo />
</div> </div>
<el-row class="left-div"> <el-row class="left-div">
<el-col <el-col :span="8" v-for="i in plateList" :key="i.id" class="plate" :style="{
:span="8" 'padding-left': i % 3 == 1 ? 0 : 0.2 + 'rem',
v-for="i in plateList" 'padding-right': i % 3 == 0 ? 0 : 0.2 + 'rem',
:key="i.id" }">
class="plate" <PlateCard :name="i.name" :introduction="i.introduction" :id="i.id" :isPublish="i.isDisableCreateDiscuss" />
:style="{
'padding-left': i % 3 == 1 ? 0 : 0.2 + 'rem',
'padding-right': i % 3 == 0 ? 0 : 0.2 + 'rem',
}"
>
<PlateCard
:name="i.name"
:introduction="i.introduction"
:id="i.id"
:isPublish="i.isDisableCreateDiscuss"
/>
</el-col> </el-col>
<template v-if="isDiscussFinished"> <template v-if="isDiscussFinished">
<el-col :span="24" v-for="i in discussList" :key="i.id"> <el-col :span="24" v-for="i in discussList" :key="i.id">
@@ -49,11 +38,7 @@
<div class="carousel-font" :style="{ color: item.color }"> <div class="carousel-font" :style="{ color: item.color }">
{{ item.name }} {{ item.name }}
</div> </div>
<el-image <el-image style="width: 100%; height: 100%" :src="item.logo" fit="cover" />
style="width: 100%; height: 100%"
:src="item.logo"
fit="cover"
/>
</el-carousel-item> </el-carousel-item>
</el-carousel> </el-carousel>
</el-col> </el-col>
@@ -101,20 +86,22 @@
</el-col> </el-col>
<el-col :span="24"> <el-col :span="24">
<InfoCard header="访问统计" class="VisitsLineChart" text="详情"> <InfoCard header="访问统计" class="VisitsLineChart" text="(New)全站历史统计" @onClickText="onClickAccessLog">
<template #content> <template #content>
<VisitsLineChart :option="statisOptions" class="statisChart" /> <VisitsLineChart :option="statisOptions" class="statisChart" />
</template> </template>
</InfoCard> </InfoCard>
<el-dialog v-model="accessLogDialogVisible" title="全站历史统计" width="1200px" center>
<AccessLogChart :option="accessLogOptins" class="accessLogChart" />
</el-dialog>
</el-col> </el-col>
<el-col :span="24"> <el-col :span="24">
<InfoCard header="简介" text="详情"> <InfoCard header="简介" text="">
<template #content> <template #content>
<div class="introduce"> <div class="introduce">
没有什么能够阻挡人类对代码<span style="color: #1890ff" 没有什么能够阻挡人类对代码<span style="color: #1890ff">优雅</span>的追求
>优雅</span
>的追求
</div> </div>
</template> </template>
</InfoCard> </InfoCard>
@@ -122,12 +109,7 @@
<el-col :span="24"> <el-col :span="24">
<template v-if="isPointFinished"> <template v-if="isPointFinished">
<InfoCard <InfoCard :items="pointList" header="财富排行榜" text="关于钱钱" height="400">
:items="pointList"
header="财富排行榜"
text="关于钱钱"
height="400"
>
<template #item="temp"> <template #item="temp">
<PointsRanking :pointsData="temp" /> <PointsRanking :pointsData="temp" />
</template> </template>
@@ -135,19 +117,16 @@
</template> </template>
<template v-else> <template v-else>
<InfoCard header="本月排行" text="更多"> <InfoCard header="本月排行" text="更多">
<template #content> <Skeleton /></template> <template #content>
<Skeleton />
</template>
</InfoCard> </InfoCard>
</template> </template>
</el-col> </el-col>
<el-col :span="24"> <el-col :span="24">
<template v-if="isFriendFinished"> <template v-if="isFriendFinished">
<InfoCard <InfoCard :items="friendList" header="推荐好友" text="更多" height="400">
:items="friendList"
header="推荐好友"
text="更多"
height="400"
>
<template #item="temp"> <template #item="temp">
<RecommendFriend :friendData="temp" /> <RecommendFriend :friendData="temp" />
</template> </template>
@@ -155,18 +134,15 @@
</template> </template>
<template v-else> <template v-else>
<InfoCard header="推荐好友" text="更多"> <InfoCard header="推荐好友" text="更多">
<template #content> <Skeleton /></template> <template #content>
<Skeleton />
</template>
</InfoCard> </InfoCard>
</template> </template>
</el-col> </el-col>
<el-col :span="24"> <el-col :span="24">
<template v-if="isThemeFinished"> <template v-if="isThemeFinished">
<InfoCard <InfoCard :items="themeList" header="推荐主题" text="更多" height="400">
:items="themeList"
header="推荐主题"
text="更多"
height="400"
>
<template #item="temp"> <template #item="temp">
<ThemeData :themeData="temp" /> <ThemeData :themeData="temp" />
</template> </template>
@@ -174,7 +150,9 @@
</template> </template>
<template v-else> <template v-else>
<InfoCard header="推荐主题" text="更多"> <InfoCard header="推荐主题" text="更多">
<template #content> <Skeleton /></template> <template #content>
<Skeleton />
</template>
</InfoCard> </InfoCard>
</template> </template>
</el-col> </el-col>
@@ -197,7 +175,8 @@ import PlateCard from "@/components/PlateCard.vue";
import ScrollbarInfo from "@/components/ScrollbarInfo.vue"; import ScrollbarInfo from "@/components/ScrollbarInfo.vue";
import BottomInfo from "@/components/BottomInfo.vue"; import BottomInfo from "@/components/BottomInfo.vue";
import VisitsLineChart from "./components/VisitsLineChart/index.vue"; import VisitsLineChart from "./components/VisitsLineChart/index.vue";
import { access } from "@/apis/accessApi.js"; import AccessLogChart from "./components/AccessLogChart/Index.vue"
import { access, getAccessList } from "@/apis/accessApi.js";
import { getList } from "@/apis/plateApi.js"; import { getList } from "@/apis/plateApi.js";
import { getList as bannerGetList } from "@/apis/bannerApi.js"; import { getList as bannerGetList } from "@/apis/bannerApi.js";
import { getHomeDiscuss } from "@/apis/discussApi.js"; import { getHomeDiscuss } from "@/apis/discussApi.js";
@@ -215,10 +194,10 @@ import ThemeData from "./components/RecommendTheme/index.vue";
import Skeleton from "@/components/Skeleton/index.vue"; import Skeleton from "@/components/Skeleton/index.vue";
import useSocketStore from "@/stores/socket"; import useSocketStore from "@/stores/socket";
const accessLogDialogVisible = ref(false)
const router = useRouter(); const router = useRouter();
const accessAllList = ref([]);
const plateList = ref([]); const plateList = ref([]);
const discussList = ref([]); const discussList = ref([]);
@@ -294,6 +273,25 @@ const statisOptions = computed(() => {
}, },
}; };
}); });
//历史全部访问统计
const accessLogOptins = computed(() => {
return {
xAxis: {
data: accessAllList.value?.map((item,index)=>{
return item.creationTime.slice(0, 10);
})
},
series: [
{
data: accessAllList.value?.map((item,index)=>{
return item.number;
})
}
]
}
});
const handleToSign = () => { const handleToSign = () => {
router.push("/activity/sign"); router.push("/activity/sign");
@@ -309,12 +307,19 @@ watch(
{ deep: true } { deep: true }
); );
const onClickAccessLog = async () => {
accessLogDialogVisible.value = true;
const {data} = await getAccessList();
accessAllList.value = data;
}
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.home-box { .home-box {
width: 1300px; width: 1300px;
height: 100%; height: 100%;
.introduce { .introduce {
color: rgba(0, 0, 0, 0.45); color: rgba(0, 0, 0, 0.45);
font-size: small; font-size: small;
@@ -350,6 +355,7 @@ watch(
display: block; display: block;
margin-bottom: 0.5rem; margin-bottom: 0.5rem;
} }
.analyse { .analyse {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
@@ -357,6 +363,7 @@ watch(
width: 100%; width: 100%;
height: 100px; height: 100px;
margin-bottom: 10px; margin-bottom: 10px;
.item { .item {
width: 30%; width: 30%;
height: 100%; height: 100%;
@@ -368,6 +375,7 @@ watch(
border: 1px solid #409eff; border: 1px solid #409eff;
border-radius: 5px; border-radius: 5px;
color: #409eff; color: #409eff;
.content { .content {
width: 100%; width: 100%;
height: 100%; height: 100%;
@@ -385,6 +393,7 @@ watch(
.name { .name {
font-size: 14px; font-size: 14px;
} }
.count { .count {
font-size: 20px; font-size: 20px;
font-weight: bold; font-weight: bold;
@@ -407,11 +416,13 @@ watch(
} }
} }
} }
.signIn { .signIn {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
color: #8a919f; color: #8a919f;
&-btn { &-btn {
cursor: pointer; cursor: pointer;
display: flex; display: flex;
@@ -426,7 +437,7 @@ watch(
} }
} }
.VisitsLineChart >>> .el-card__body { .VisitsLineChart>>>.el-card__body {
padding: 0.5rem; padding: 0.5rem;
} }
@@ -434,5 +445,10 @@ watch(
width: 100%; width: 100%;
height: 300px; height: 300px;
} }
.accessLogChart {
width: 1100px;
height: 500px;
}
} }
</style> </style>

View File

@@ -0,0 +1,31 @@
<template>
<div class="v-chart" ref="statis"></div>
</template>
<script setup name="AccessLogChart">
import { ref, defineEmits, defineProps, defineExpose } from "vue";
import useEcharts from "@/hooks/useEcharts";
import { accessLogEchartsConfig } from "../../hooks/accessLogEchartsConfig";
const props = defineProps({
option: {
type: Object,
default: () => {},
},
});
const emits = defineEmits([
"chart-click", // 点击chart
]);
let statis = ref(null);
const { resize } = useEcharts(statis, emits, props, accessLogEchartsConfig);
defineExpose({
resize,
});
</script>
<style scoped lang="scss">
.v-chart {
width: 100%;
height: 100%;
}
</style>

View File

@@ -0,0 +1,18 @@
export const accessLogEchartsConfig = {
xAxis: {
type: 'category',
boundaryGap: false,
data: []
},
yAxis: {
type: 'value'
},
series: [
{
data: [],
type: 'line',
areaStyle: {}
}
]
};