forked from bot/app
🐛 [docs]: 增加访客记录
This commit is contained in:
parent
e493139d85
commit
be59e241c6
@ -1,7 +1,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import DefaultTheme from "vitepress/theme";
|
import DefaultTheme from "vitepress/theme";
|
||||||
import {ref, onMounted, onUnmounted} from "vue";
|
import {ref, onMounted, onUnmounted} from "vue";
|
||||||
import {statsApi, GithubStats, RepoUrl, StarMapUrl} from "./scripts/statsApi";
|
import {statsApi, GithubStats, RepoUrl, StarMapUrl, uploadVisitRecord} from "./scripts/statsApi";
|
||||||
import {getTextRef, updateRefData} from "./scripts/i18n";
|
import {getTextRef, updateRefData} from "./scripts/i18n";
|
||||||
import {onBeforeRouteUpdate} from 'vue-router';
|
import {onBeforeRouteUpdate} from 'vue-router';
|
||||||
|
|
||||||
@ -58,6 +58,12 @@ const dataSections = {
|
|||||||
value: ref(6789),
|
value: ref(6789),
|
||||||
link: './store/resource'
|
link: './store/resource'
|
||||||
},
|
},
|
||||||
|
visitors: {
|
||||||
|
name: 'visitors',
|
||||||
|
color: '#00a6ff',
|
||||||
|
value: ref(1234),
|
||||||
|
link: RepoUrl
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
async function updateData() {
|
async function updateData() {
|
||||||
@ -68,6 +74,7 @@ async function updateData() {
|
|||||||
dataSections.total.value.value,
|
dataSections.total.value.value,
|
||||||
dataSections.plugins.value.value,
|
dataSections.plugins.value.value,
|
||||||
dataSections.resources.value.value,
|
dataSections.resources.value.value,
|
||||||
|
dataSections.visitors.value.value,
|
||||||
githubStats,
|
githubStats,
|
||||||
|
|
||||||
] = await Promise.all([
|
] = await Promise.all([
|
||||||
@ -75,6 +82,7 @@ async function updateData() {
|
|||||||
statsApi.getTotal(),
|
statsApi.getTotal(),
|
||||||
statsApi.getPluginNum(),
|
statsApi.getPluginNum(),
|
||||||
statsApi.getResourceNum(),
|
statsApi.getResourceNum(),
|
||||||
|
statsApi.getVisitCount(),
|
||||||
statsApi.getGithubStats(),
|
statsApi.getGithubStats(),
|
||||||
]);
|
]);
|
||||||
dataSections.stars.value.value = githubStats?.stars || 0;
|
dataSections.stars.value.value = githubStats?.stars || 0;
|
||||||
@ -83,11 +91,15 @@ async function updateData() {
|
|||||||
dataSections.prs.value.value = githubStats?.prs || 0;
|
dataSections.prs.value.value = githubStats?.prs || 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function formatNumber(num: { value: number }): string {
|
||||||
|
return num.value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
const intervalId = setInterval(updateData, 10000);
|
const intervalId = setInterval(updateData, 10000);
|
||||||
updateData();
|
updateData();
|
||||||
updateRefData();
|
uploadVisitRecord();
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
clearInterval(intervalId);
|
clearInterval(intervalId);
|
||||||
});
|
});
|
||||||
@ -97,6 +109,8 @@ onBeforeRouteUpdate(() => {
|
|||||||
updateRefData();
|
updateRefData();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -113,7 +127,7 @@ onBeforeRouteUpdate(() => {
|
|||||||
<span class="dot" :style="{backgroundColor: section.color}"></span>
|
<span class="dot" :style="{backgroundColor: section.color}"></span>
|
||||||
<span class="text">{{ getTextRef(section.name) }}</span>
|
<span class="text">{{ getTextRef(section.name) }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="number">{{ section.value.value }}</div>
|
<div class="number">{{ formatNumber(section.value) }}</div>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -222,7 +236,7 @@ onBeforeRouteUpdate(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.number {
|
.number {
|
||||||
font-size: 30px;
|
font-size: 27px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
margin-top: 5px;
|
margin-top: 5px;
|
||||||
margin-left: 15px;
|
margin-left: 15px;
|
||||||
|
@ -13,6 +13,7 @@ const i18nData = {
|
|||||||
forks: 'Forks',
|
forks: 'Forks',
|
||||||
issues: 'Issues',
|
issues: 'Issues',
|
||||||
prs: 'Pull Requests',
|
prs: 'Pull Requests',
|
||||||
|
visitors: 'Visitor',
|
||||||
size: 'Size',
|
size: 'Size',
|
||||||
plugins: 'Plugins',
|
plugins: 'Plugins',
|
||||||
resources: 'Resources',
|
resources: 'Resources',
|
||||||
@ -32,6 +33,7 @@ const i18nData = {
|
|||||||
forks: '叉子',
|
forks: '叉子',
|
||||||
issues: '开启议题',
|
issues: '开启议题',
|
||||||
prs: '合并请求',
|
prs: '合并请求',
|
||||||
|
visitors: '访客',
|
||||||
size: '大小',
|
size: '大小',
|
||||||
plugins: '插件',
|
plugins: '插件',
|
||||||
resources: '主题资源',
|
resources: '主题资源',
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
|
|
||||||
// URL
|
// URL
|
||||||
export const OWNER = "LiteyukiStudio"
|
export const OWNER = "LiteyukiStudio"
|
||||||
export const REPO = "LiteyukiBot"
|
export const REPO = "LiteyukiBot"
|
||||||
const githubAPIUrl = "https://api.github.com"
|
const githubAPIUrl = "https://api.github.com"
|
||||||
const onlineFetchUrl = "https://api.liteyuki.icu/online";
|
const onlineFetchUrl = "https://api.liteyuki.icu/online";
|
||||||
const totalFetchUrl = "https://api.liteyuki.icu/count";
|
const totalFetchUrl = "https://api.liteyuki.icu/count";
|
||||||
|
const visitRecordUrl = "https://api.liteyuki.icu/visit";
|
||||||
|
const visitCountUrl = "https://api.liteyuki.icu/visit_count";
|
||||||
|
|
||||||
export const RepoUrl = `https://github.com/${OWNER}/${REPO}`
|
export const RepoUrl = `https://github.com/${OWNER}/${REPO}`
|
||||||
export const StarMapUrl = "https://starmap.liteyuki.icu"
|
export const StarMapUrl = "https://starmap.liteyuki.icu"
|
||||||
@ -25,10 +26,11 @@ interface StatsApi {
|
|||||||
getGithubStats: () => Promise<GithubStats>;
|
getGithubStats: () => Promise<GithubStats>;
|
||||||
getPluginNum: () => Promise<number>;
|
getPluginNum: () => Promise<number>;
|
||||||
getResourceNum: () => Promise<number>;
|
getResourceNum: () => Promise<number>;
|
||||||
|
getVisitCount: () => Promise<number>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export type { GithubStats };
|
export type {GithubStats};
|
||||||
|
|
||||||
// 实现接口
|
// 实现接口
|
||||||
export const statsApi: StatsApi = {
|
export const statsApi: StatsApi = {
|
||||||
@ -90,5 +92,48 @@ export const statsApi: StatsApi = {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
getVisitCount: async () => {
|
||||||
|
try {
|
||||||
|
const res = await fetch(visitCountUrl);
|
||||||
|
const data = await res.json();
|
||||||
|
return data.count;
|
||||||
|
} catch (e) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function getDeviceId(): string {
|
||||||
|
// 用户每次访问时生成一个唯一的设备ID,储存在localStorage中,用于统计用户数量
|
||||||
|
const deviceIdKey = 'deviceId';
|
||||||
|
let deviceId = localStorage.getItem(deviceIdKey);
|
||||||
|
|
||||||
|
if (!deviceId) {
|
||||||
|
deviceId = generateUUID();
|
||||||
|
localStorage.setItem(deviceIdKey, deviceId);
|
||||||
|
}
|
||||||
|
return deviceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function uploadVisitRecord() {
|
||||||
|
const deviceId = getDeviceId();
|
||||||
|
try {
|
||||||
|
await fetch(visitRecordUrl, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/x-www-form-urlencoded'
|
||||||
|
},
|
||||||
|
body: new URLSearchParams({'device_id': deviceId}).toString(),
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Failed to upload visit record:', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateUUID(): string {
|
||||||
|
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
|
||||||
|
var r = (Math.random() * 16) | 0, v = c === 'x' ? r : (r & 0x3 | 0x8);
|
||||||
|
return v.toString(16);
|
||||||
|
});
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user