Skip to content

Commit 7a776bb

Browse files
committed
feat(vitepress): 添加访客统计
1 parent 388ece7 commit 7a776bb

File tree

9 files changed

+161
-5
lines changed

9 files changed

+161
-5
lines changed

docs/.vitepress/config.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ export default defineConfig({
5252
prev: '上一篇',
5353
next: '下一篇',
5454
},
55+
56+
visitor: {
57+
badgeId: 'maomao1996.vitepress-nav-template',
58+
},
5559
},
5660

5761
vite: {
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
<script setup lang="ts">
2+
import { inject, Ref, computed } from 'vue'
3+
import { useData } from 'vitepress'
4+
import { useSidebar } from 'vitepress/theme'
5+
6+
import { usePageId } from '../composables'
7+
8+
const DEV = inject<Ref<boolean>>('DEV')
9+
const { theme } = useData()
10+
const { footer, visitor } = theme.value
11+
12+
const { hasSidebar } = useSidebar()
13+
const pageId = usePageId()
14+
15+
const isDocFooterVisible = computed(() => {
16+
return !DEV || footer.message || footer.copyright || visitor.badgeId
17+
})
18+
</script>
19+
20+
<template>
21+
<div v-if="isDocFooterVisible" v-show="hasSidebar" class="m-doc-footer">
22+
<div class="m-doc-footer-message">
23+
<img
24+
v-if="!DEV && visitor"
25+
class="visitor"
26+
:src="`https://visitor-badge.laobi.icu/badge?page_id=${visitor.badgeId}.${pageId}`"
27+
title="当前页面累计访问数"
28+
onerror="this.style.display='none'"
29+
/>
30+
<p v-if="footer?.message">{{ footer.message }}</p>
31+
</div>
32+
<p class="m-doc-footer-copyright" v-if="footer?.copyright">
33+
{{ footer.copyright }}
34+
</p>
35+
</div>
36+
</template>
37+
38+
<style scoped>
39+
.m-doc-footer {
40+
display: flex;
41+
flex-direction: column;
42+
align-items: center;
43+
margin-top: 24px;
44+
border-top: 1px solid var(--vp-c-gutter);
45+
padding: 32px 24px 0;
46+
line-height: 24px;
47+
font-size: 14px;
48+
font-weight: 500;
49+
color: var(--vp-c-text-2);
50+
}
51+
52+
.m-doc-footer-message,
53+
.m-doc-footer-copyright {
54+
display: flex;
55+
align-items: center;
56+
}
57+
58+
.visitor {
59+
margin-right: 8px;
60+
}
61+
62+
@media (max-width: 414px) {
63+
.visitor {
64+
display: none;
65+
}
66+
}
67+
</style>

docs/.vitepress/theme/components/MLayout.vue

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ import { useData } from 'vitepress'
33
import DefaultTheme from 'vitepress/theme'
44
import { nextTick, provide } from 'vue'
55
6+
import MNavVisitor from './MNavVisitor.vue'
7+
import MDocFooter from './MDocFooter.vue'
8+
69
const { Layout } = DefaultTheme
710
const { isDark } = useData()
811
@@ -42,5 +45,17 @@ provide('toggle-appearance', async ({ clientX: x, clientY: y }: MouseEvent) => {
4245
</script>
4346

4447
<template>
45-
<Layout v-bind="$attrs" />
48+
<Layout v-bind="$attrs">
49+
<!--
50+
相关插槽
51+
https://vitepress.dev/zh/guide/extending-default-theme#layout-slots
52+
https://github.com/vuejs/vitepress/blob/main/src/client/theme-default/Layout.vue
53+
-->
54+
<template #nav-bar-title-after>
55+
<MNavVisitor />
56+
</template>
57+
<template #doc-after>
58+
<MDocFooter />
59+
</template>
60+
</Layout>
4661
</template>
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<script setup lang="ts">
2+
import { useData } from 'vitepress'
3+
import { inject, Ref } from 'vue'
4+
5+
const DEV = inject<Ref<boolean>>('DEV')
6+
const { theme } = useData()
7+
const { visitor } = theme.value
8+
</script>
9+
10+
<template>
11+
<img
12+
v-if="!DEV && visitor"
13+
class="visitor"
14+
:src="`https://visitor-badge.laobi.icu/badge?page_id=${visitor.badgeId}`"
15+
onerror="this.style.display='none'"
16+
/>
17+
</template>
18+
19+
<style scoped>
20+
.visitor {
21+
margin-left: 8px;
22+
}
23+
24+
@media (min-width: 768px) and (max-width: 920px) {
25+
.visitor {
26+
display: none;
27+
}
28+
}
29+
</style>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export * from './useFormatPath'
2+
export * from './useMediumZoom'
3+
export * from './usePageId'
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { useData, useRoute } from 'vitepress'
2+
import { computed } from 'vue'
3+
4+
/**
5+
* 对 route.path 进行格式化,统一 github pages 和其他部署平台的 route.path
6+
*/
7+
export function useFormatPath() {
8+
const { site } = useData()
9+
const route = useRoute()
10+
11+
return computed(() => route.path.replace(site.value.base.replace(/\/$/, ''), ''))
12+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { computed } from 'vue'
2+
import { useData } from 'vitepress'
3+
4+
import { useFormatPath } from '../composables'
5+
6+
/**
7+
* 获取当前页面的 pageId 用于页面统计和评论(默认为 route.path)
8+
*/
9+
export function usePageId() {
10+
const { frontmatter } = useData()
11+
const formatPath = useFormatPath()
12+
13+
return computed(() => frontmatter.value.pageId || formatPath.value)
14+
}

docs/.vitepress/theme/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ export default {
2828
enhanceApp({ app, router }: EnhanceAppContext) {
2929
createMediumZoomProvider(app, router)
3030

31+
app.provide('DEV', process.env.NODE_ENV === 'development')
32+
3133
app.component('MNavLinks', MNavLinks)
3234

3335
if (typeof window !== 'undefined') {

env.d.ts

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,17 @@
11
/// <reference types="vitepress/client" />
22

3-
declare module '*.vue' {
4-
import { DefineComponent } from 'vue'
5-
const component: DefineComponent<{}, {}, any>
6-
export default component
3+
import { DefaultTheme } from 'vitepress'
4+
5+
declare module 'vitepress' {
6+
export namespace DefaultTheme {
7+
export interface Config {
8+
/**
9+
* 访客统计配置
10+
*/
11+
visitor?: {
12+
/** 统计 id(单独页面的统计会作为前缀使用)*/
13+
badgeId: string
14+
}
15+
}
16+
}
717
}

0 commit comments

Comments
 (0)