LiteyukiBot/docs/components/StatsBar.vue

273 lines
5.9 KiB
Vue
Raw Normal View History

2024-09-01 10:25:37 +00:00
<script setup lang="ts">
2024-09-01 12:39:51 +00:00
import DefaultTheme from "vitepress/theme";
2024-09-01 14:30:46 +00:00
import {ref, onMounted, onUnmounted} from "vue";
2024-09-01 13:16:45 +00:00
import {statsApi, GithubStats, RepoUrl, StarMapUrl} from "./scripts/statsApi";
2024-09-01 14:00:17 +00:00
import {getTextRef, updateRefData} from "./scripts/i18n";
2024-09-01 14:30:46 +00:00
import {onBeforeRouteUpdate} from 'vue-router';
2024-09-01 12:39:51 +00:00
const {Layout} = DefaultTheme;
let githubStats: GithubStats | null = null;
const dataSections = {
total: {
name: 'total',
color: '#00a6ff',
2024-09-01 13:16:45 +00:00
value: ref(2005),
link: StarMapUrl
2024-09-01 12:39:51 +00:00
},
online: {
name: 'online',
2024-09-01 14:52:00 +00:00
color: '#7eff7e',
2024-09-01 13:16:45 +00:00
value: ref(1145),
link: StarMapUrl
2024-09-01 12:39:51 +00:00
},
stars: {
name: 'stars',
color: '#ffcc00',
2024-09-01 13:16:45 +00:00
value: ref(1234),
link: `${RepoUrl}/stargazers`
2024-09-01 12:39:51 +00:00
},
forks: {
name: 'forks',
color: '#ff6600',
2024-09-01 13:16:45 +00:00
value: ref(9420),
link: `${RepoUrl}/forks`
2024-09-01 12:39:51 +00:00
},
issues: {
name: 'issues',
color: '#ff0000',
2024-09-01 13:16:45 +00:00
value: ref(1145),
link: `${RepoUrl}/issues`
2024-09-01 12:39:51 +00:00
},
prs: {
name: 'prs',
2024-09-01 14:52:00 +00:00
color: '#f15df1',
2024-09-01 13:16:45 +00:00
value: ref(6543),
link: `${RepoUrl}/pulls`
},
plugins: {
name: 'plugins',
2024-09-01 14:52:00 +00:00
color: '#a766ff',
2024-09-01 13:16:45 +00:00
value: ref(1763),
link: './store/plugin'
},
resources: {
name: 'resources',
2024-09-01 14:52:00 +00:00
color: '#5a54fa',
2024-09-01 13:16:45 +00:00
value: ref(6789),
link: './store/resource'
2024-09-01 12:39:51 +00:00
},
}
2024-09-01 10:25:37 +00:00
2024-09-01 12:39:51 +00:00
async function updateData() {
// dataSections.online.value.value = await statsApi.getOnline();
// dataSections.total.value.value = await statsApi.getTotal();
[
dataSections.online.value.value,
dataSections.total.value.value,
2024-09-01 13:16:45 +00:00
dataSections.plugins.value.value,
dataSections.resources.value.value,
2024-09-01 12:39:51 +00:00
githubStats,
2024-09-01 13:16:45 +00:00
2024-09-01 12:39:51 +00:00
] = await Promise.all([
statsApi.getOnline(),
statsApi.getTotal(),
2024-09-01 13:16:45 +00:00
statsApi.getPluginNum(),
statsApi.getResourceNum(),
2024-09-01 12:39:51 +00:00
statsApi.getGithubStats(),
]);
dataSections.stars.value.value = githubStats?.stars || 0;
dataSections.forks.value.value = githubStats?.forks || 0;
dataSections.issues.value.value = githubStats?.issues || 0;
dataSections.prs.value.value = githubStats?.prs || 0;
2024-09-01 08:52:10 +00:00
}
2024-09-01 14:00:17 +00:00
2024-09-01 10:25:37 +00:00
onMounted(() => {
const intervalId = setInterval(updateData, 10000);
updateData();
2024-09-01 14:00:17 +00:00
updateRefData();
2024-09-01 10:25:37 +00:00
onUnmounted(() => {
clearInterval(intervalId);
});
});
2024-09-01 08:52:10 +00:00
2024-09-01 14:00:17 +00:00
onBeforeRouteUpdate(() => {
updateRefData();
});
2024-09-01 08:52:10 +00:00
</script>
<template>
2024-09-01 12:39:51 +00:00
<Layout>
<template #home-features-before>
<div class="stats-bar-content">
<div class="stats-bar">
<div class="stats-info">
2024-09-01 14:30:46 +00:00
<div class="stats-title">{{ getTextRef('stats') }}</div>
<div class="sections">
<div v-for="section in Object.values(dataSections)" :key="section.name" class="section">
<a :href="section.link" target="_blank">
<div class="section-tab">
<span class="dot" :style="{backgroundColor: section.color}"></span>
<span class="text">{{ getTextRef(section.name) }}</span>
</div>
<div class="number">{{ section.value.value }}</div>
</a>
</div>
2024-09-01 12:39:51 +00:00
</div>
</div>
<div class="starmap">
2024-09-01 14:42:20 +00:00
<iframe src="https://starmap.liteyuki.icu/" width="100%" height="300px" class="gamma"></iframe>
2024-09-01 12:39:51 +00:00
</div>
2024-09-01 09:57:21 +00:00
</div>
2024-09-01 08:52:10 +00:00
</div>
2024-09-01 12:39:51 +00:00
</template>
</Layout>
2024-09-01 08:52:10 +00:00
</template>
<style scoped>
2024-09-01 09:57:21 +00:00
2024-09-01 12:39:51 +00:00
.stats-bar-content {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
2024-09-01 14:42:20 +00:00
.gamma {
filter: brightness(1.8);
}
.dark .gamma {
filter: brightness(1.0);
}
2024-09-01 09:57:21 +00:00
.stats-bar {
2024-09-01 12:39:51 +00:00
width: 80%;
max-width: 1150px;
2024-09-01 08:52:10 +00:00
display: flex;
2024-09-01 09:57:21 +00:00
justify-content: space-between;
2024-09-01 08:52:10 +00:00
padding: 20px;
2024-09-01 13:16:45 +00:00
margin: 10px;
2024-09-01 09:57:21 +00:00
border-radius: var(--border-radius-2);
2024-09-01 08:52:10 +00:00
background-color: var(--vp-c-gray-1);
2024-09-01 09:57:21 +00:00
flex-direction: column; /* 默认纵向布局 */
}
2024-09-01 14:30:46 +00:00
.stats-info{
margin-bottom: 20px;
}
.stats-title {
font-size: 20px;
font-weight: bold;
margin-bottom: 20px;
text-align: center;
}
.sections {
height: 100%;
2024-09-01 09:57:21 +00:00
width: 100%;
2024-09-01 12:39:51 +00:00
display: grid;
2024-09-01 12:44:50 +00:00
grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
2024-09-01 12:39:51 +00:00
gap: 15px;
2024-09-01 13:16:45 +00:00
margin: 10px;
2024-09-01 09:57:21 +00:00
}
.section {
display: flex;
flex-direction: column;
2024-09-01 13:16:45 +00:00
position: relative; /* 使伪元素相对于父元素定位 */
border-radius: var(--border-radius-2);
}
.section::before {
content: '';
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
border: 0 solid transparent; /* 初始边框为透明 */
transition: border 0.1s ease-in-out; /* 添加过渡效果 */
border-radius: var(--border-radius-2);
pointer-events: none; /* 确保伪元素不会阻挡点击事件 */
}
.section:hover::before {
border: 1px solid #00a6ff; /* 悬停时添加边框 */
border-radius: var(--border-radius-2);
2024-09-01 08:52:10 +00:00
}
2024-09-01 12:39:51 +00:00
.section-tab {
2024-09-01 12:44:50 +00:00
margin-left: 15px;
2024-09-01 12:39:51 +00:00
display: flex;
justify-content: flex-start;
align-items: center; /* 确保垂直居中 */
2024-09-01 08:52:10 +00:00
}
.dot {
width: 10px;
height: 10px;
border-radius: 50%;
margin-right: 5px;
}
2024-09-01 09:57:21 +00:00
.text {
font-size: 14px;
2024-09-01 12:39:51 +00:00
white-space: nowrap;
align-items: center;
2024-09-01 09:57:21 +00:00
}
2024-09-01 08:52:10 +00:00
.number {
font-size: 30px;
font-weight: bold;
margin-top: 5px;
2024-09-01 12:44:50 +00:00
margin-left: 15px;
2024-09-01 08:52:10 +00:00
}
2024-09-01 09:57:21 +00:00
.starmap {
position: relative;
width: 100%;
height: 200px;
overflow: hidden;
border-radius: var(--border-radius-2);
}
.starmap iframe {
position: absolute;
top: -150px; /* 根据需要调整裁剪位置 */
left: -40px; /* 根据需要调整裁剪位置 */;
width: calc(100% + 80px); /* 根据需要调整裁剪宽度 */
height: calc(100% + 300px); /* 根据需要调整裁剪高度 */
}
@media (min-width: 768px) {
/* PC模式下的样式 */
.stats-bar {
flex-direction: row;
2024-09-01 13:16:45 +00:00
margin: 30px;
2024-09-01 09:57:21 +00:00
}
.stats-info {
width: 40%;
2024-09-01 14:30:46 +00:00
margin: 30px;
2024-09-01 09:57:21 +00:00
}
.starmap {
width: 60%;
height: 400px;
}
.starmap iframe {
position: absolute;
top: -130px; /* 根据需要调整裁剪位置 */
left: -60px; /* 根据需要调整裁剪位置 */;
width: calc(100% + 120px); /* 根据需要调整裁剪宽度 */
height: calc(100% + 280px); /* 根据需要调整裁剪高度 */
}
}
2024-09-01 08:52:10 +00:00
</style>