mirror of https://github.com/halo-dev/halo-admin
feat: support for displaying site content statistics (#624)
#### What type of PR is this? /kind feature /milestone 2.0 #### What this PR does / why we need it: - 支持在文章和自定义页面的管理列表显示访问数和评论数。 - 仪表盘支持显示整站的访问数。 适配 https://github.com/halo-dev/halo/pull/2476 #### Which issue(s) this PR fixes: Fixes https://github.com/halo-dev/halo/issues/2430 #### Special notes for your reviewer: /cc @halo-dev/sig-halo-console 测试方式: 1. Halo 需要 https://github.com/halo-dev/halo/pull/2476 PR 中的分支。 2. 需要执行 `pnpm install && pnpm build:packages` 3. 随机访问前台文章或者自定义页面,以及添加评论。 4. 查看后台是否正确统计文章浏览数和评论数。 TODO list: - [ ] 更新 `@halo-dev/api-client` #### Does this PR introduce a user-facing change? ```release-note 支持在文章和自定义页面的管理列表显示访问数和评论数 ```pull/633/head
parent
bdd8632647
commit
e98f3e19ad
|
@ -34,7 +34,7 @@
|
||||||
"@formkit/themes": "1.0.0-beta.10",
|
"@formkit/themes": "1.0.0-beta.10",
|
||||||
"@formkit/vue": "1.0.0-beta.10",
|
"@formkit/vue": "1.0.0-beta.10",
|
||||||
"@halo-dev/admin-shared": "workspace:*",
|
"@halo-dev/admin-shared": "workspace:*",
|
||||||
"@halo-dev/api-client": "^0.0.34",
|
"@halo-dev/api-client": "^0.0.35",
|
||||||
"@halo-dev/components": "workspace:*",
|
"@halo-dev/components": "workspace:*",
|
||||||
"@halo-dev/richtext-editor": "^0.0.0-alpha.7",
|
"@halo-dev/richtext-editor": "^0.0.0-alpha.7",
|
||||||
"@tiptap/extension-character-count": "2.0.0-beta.31",
|
"@tiptap/extension-character-count": "2.0.0-beta.31",
|
||||||
|
|
|
@ -14,7 +14,7 @@ importers:
|
||||||
'@formkit/themes': 1.0.0-beta.10
|
'@formkit/themes': 1.0.0-beta.10
|
||||||
'@formkit/vue': 1.0.0-beta.10
|
'@formkit/vue': 1.0.0-beta.10
|
||||||
'@halo-dev/admin-shared': workspace:*
|
'@halo-dev/admin-shared': workspace:*
|
||||||
'@halo-dev/api-client': ^0.0.34
|
'@halo-dev/api-client': ^0.0.35
|
||||||
'@halo-dev/components': workspace:*
|
'@halo-dev/components': workspace:*
|
||||||
'@halo-dev/richtext-editor': ^0.0.0-alpha.7
|
'@halo-dev/richtext-editor': ^0.0.0-alpha.7
|
||||||
'@iconify-json/mdi': ^1.1.33
|
'@iconify-json/mdi': ^1.1.33
|
||||||
|
@ -101,7 +101,7 @@ importers:
|
||||||
'@formkit/themes': 1.0.0-beta.10_tailwindcss@3.1.8
|
'@formkit/themes': 1.0.0-beta.10_tailwindcss@3.1.8
|
||||||
'@formkit/vue': 1.0.0-beta.10_k5hp3txgeyj6le63abiyc7wx3u
|
'@formkit/vue': 1.0.0-beta.10_k5hp3txgeyj6le63abiyc7wx3u
|
||||||
'@halo-dev/admin-shared': link:packages/shared
|
'@halo-dev/admin-shared': link:packages/shared
|
||||||
'@halo-dev/api-client': 0.0.34
|
'@halo-dev/api-client': 0.0.35
|
||||||
'@halo-dev/components': link:packages/components
|
'@halo-dev/components': link:packages/components
|
||||||
'@halo-dev/richtext-editor': 0.0.0-alpha.7_vue@3.2.40
|
'@halo-dev/richtext-editor': 0.0.0-alpha.7_vue@3.2.40
|
||||||
'@tiptap/extension-character-count': 2.0.0-beta.31
|
'@tiptap/extension-character-count': 2.0.0-beta.31
|
||||||
|
@ -1886,8 +1886,8 @@ packages:
|
||||||
- windicss
|
- windicss
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@halo-dev/api-client/0.0.34:
|
/@halo-dev/api-client/0.0.35:
|
||||||
resolution: {integrity: sha512-WOEbyRjPSASH1tyQjQQU/RjXKtRPSD+L6erAWLUfy7BIsyCAMSBdkF3auBWaevUt08uyCBeI3ln+sP+VPyFM0A==}
|
resolution: {integrity: sha512-+WBXS2/tHmeugeiDNXmBrtV9NiU22lylzwcugH/eTXGy7MnpAG4j//o2OOYyhVcp9BUBoh7MHuu0UcyLHq1bgg==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@halo-dev/richtext-editor/0.0.0-alpha.7_vue@3.2.40:
|
/@halo-dev/richtext-editor/0.0.0-alpha.7_vue@3.2.40:
|
||||||
|
|
|
@ -535,7 +535,6 @@ function handleSortItemChange(sortItem?: SortItem) {
|
||||||
<template #start>
|
<template #start>
|
||||||
<VEntityField
|
<VEntityField
|
||||||
:title="singlePage.page.spec.title"
|
:title="singlePage.page.spec.title"
|
||||||
:description="singlePage.page.status?.permalink"
|
|
||||||
:route="{
|
:route="{
|
||||||
name: 'SinglePageEditor',
|
name: 'SinglePageEditor',
|
||||||
query: { name: singlePage.page.metadata.name },
|
query: { name: singlePage.page.metadata.name },
|
||||||
|
@ -554,6 +553,19 @@ function handleSortItemChange(sortItem?: SortItem) {
|
||||||
<VStatusDot state="success" animate />
|
<VStatusDot state="success" animate />
|
||||||
</RouterLink>
|
</RouterLink>
|
||||||
</template>
|
</template>
|
||||||
|
<template #description>
|
||||||
|
<VSpace>
|
||||||
|
<span class="text-xs text-gray-500">
|
||||||
|
{{ singlePage.page.status?.permalink }}
|
||||||
|
</span>
|
||||||
|
<span class="text-xs text-gray-500">
|
||||||
|
访问量 {{ singlePage.stats.visits || 0 }}
|
||||||
|
</span>
|
||||||
|
<span class="text-xs text-gray-500">
|
||||||
|
评论 {{ singlePage.stats.comments || 0 }}
|
||||||
|
</span>
|
||||||
|
</VSpace>
|
||||||
|
</template>
|
||||||
</VEntityField>
|
</VEntityField>
|
||||||
</template>
|
</template>
|
||||||
<template #end>
|
<template #end>
|
||||||
|
|
|
@ -837,8 +837,12 @@ function handleContributorChange(user?: User) {
|
||||||
{{ category.spec.displayName }}
|
{{ category.spec.displayName }}
|
||||||
</span>
|
</span>
|
||||||
</p>
|
</p>
|
||||||
<span class="text-xs text-gray-500">访问量 0</span>
|
<span class="text-xs text-gray-500">
|
||||||
<span class="text-xs text-gray-500"> 评论 0 </span>
|
访问量 {{ post.stats.visits || 0 }}
|
||||||
|
</span>
|
||||||
|
<span class="text-xs text-gray-500">
|
||||||
|
评论 {{ post.stats.comments || 0 }}
|
||||||
|
</span>
|
||||||
</VSpace>
|
</VSpace>
|
||||||
</template>
|
</template>
|
||||||
</VEntityField>
|
</VEntityField>
|
||||||
|
|
|
@ -43,8 +43,12 @@ onMounted(handleFetchPosts);
|
||||||
</p>
|
</p>
|
||||||
<div class="mt-1 flex">
|
<div class="mt-1 flex">
|
||||||
<VSpace>
|
<VSpace>
|
||||||
<span class="text-xs text-gray-500"> 阅读 0 </span>
|
<span class="text-xs text-gray-500">
|
||||||
<span class="text-xs text-gray-500"> 评论 0 </span>
|
阅读 {{ post.stats.visits }}
|
||||||
|
</span>
|
||||||
|
<span class="text-xs text-gray-500">
|
||||||
|
评论 {{ post.stats.comments }}
|
||||||
|
</span>
|
||||||
</VSpace>
|
</VSpace>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,9 +1,25 @@
|
||||||
<script lang="ts" name="ViewsStatsWidget" setup>
|
<script lang="ts" name="ViewsStatsWidget" setup>
|
||||||
|
import { apiClient } from "@/utils/api-client";
|
||||||
|
import type { Stats } from "@halo-dev/api-client";
|
||||||
import { VCard } from "@halo-dev/components";
|
import { VCard } from "@halo-dev/components";
|
||||||
|
import { onMounted, ref } from "vue";
|
||||||
|
|
||||||
|
const stats = ref<Stats>({
|
||||||
|
visits: 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleFetchStats = async () => {
|
||||||
|
const { data } = await apiClient.stats.getStats();
|
||||||
|
stats.value = data;
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(handleFetchStats);
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<VCard class="h-full">
|
<VCard class="h-full">
|
||||||
<dt class="truncate text-sm font-medium text-gray-500">浏览量</dt>
|
<dt class="truncate text-sm font-medium text-gray-500">浏览量</dt>
|
||||||
<dd class="mt-1 text-3xl font-semibold text-gray-900">123,321</dd>
|
<dd class="mt-1 text-3xl font-semibold text-gray-900">
|
||||||
|
{{ stats.visits || 0 }}
|
||||||
|
</dd>
|
||||||
</VCard>
|
</VCard>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -7,6 +7,7 @@ import {
|
||||||
ApiConsoleHaloRunV1alpha1UserApi,
|
ApiConsoleHaloRunV1alpha1UserApi,
|
||||||
ApiConsoleHaloRunV1alpha1CommentApi,
|
ApiConsoleHaloRunV1alpha1CommentApi,
|
||||||
ApiConsoleHaloRunV1alpha1ReplyApi,
|
ApiConsoleHaloRunV1alpha1ReplyApi,
|
||||||
|
ApiConsoleHaloRunV1alpha1StatsApi,
|
||||||
ContentHaloRunV1alpha1CategoryApi,
|
ContentHaloRunV1alpha1CategoryApi,
|
||||||
ContentHaloRunV1alpha1CommentApi,
|
ContentHaloRunV1alpha1CommentApi,
|
||||||
ContentHaloRunV1alpha1PostApi,
|
ContentHaloRunV1alpha1PostApi,
|
||||||
|
@ -126,6 +127,7 @@ function setupApiClient(axios: AxiosInstance) {
|
||||||
content: new ApiConsoleHaloRunV1alpha1ContentApi(undefined, baseURL, axios),
|
content: new ApiConsoleHaloRunV1alpha1ContentApi(undefined, baseURL, axios),
|
||||||
comment: new ApiConsoleHaloRunV1alpha1CommentApi(undefined, baseURL, axios),
|
comment: new ApiConsoleHaloRunV1alpha1CommentApi(undefined, baseURL, axios),
|
||||||
reply: new ApiConsoleHaloRunV1alpha1ReplyApi(undefined, baseURL, axios),
|
reply: new ApiConsoleHaloRunV1alpha1ReplyApi(undefined, baseURL, axios),
|
||||||
|
stats: new ApiConsoleHaloRunV1alpha1StatsApi(undefined, baseURL, axios),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue