add mc server status part

This commit is contained in:
Jeffrey Hsu 2025-01-26 04:22:19 +08:00
parent 05815e3414
commit 8081d0fdda
4 changed files with 214 additions and 1 deletions

View File

@ -0,0 +1,108 @@
<script setup lang="ts">
defineProps<{
server: IMCServerStatus
}>()
</script>
<template>
<div
v-if="server.online"
class="p-4"
>
<div class="flex justify-between">
<div class="flex items-center gap-4">
<!-- Server Logo -->
<img
:src="server.icon!"
alt=""
class="h-20 w-20 rounded-xl"
>
<div>
<p class="text-2xl font-bold">
{{ server.hostname?.toUpperCase() || "UNKNOWN HOST" }}
</p>
<p class="text-xl">
{{ server.port }}
</p>
</div>
</div>
<div class="flex flex-col justify-between text-lg">
<p class="rounded-lg bg-gray-200 px-2">
{{ server.version || 'UNKNOWN VERSION' }}
</p>
<p class="rounded-lg bg-gray-200 px-2">
{{ server.players.online }} / {{ server.players.max }}
</p>
</div>
</div>
<div class="mt-4 rounded-xl bg-blue-100 p-4">
<p
v-for="line in server.motd.clean"
:key="line"
>
{{ line }}
</p>
</div>
<div class="mt-4">
<span class="text-xl">玩家列表</span>
<div
v-if="server.players.list?.length"
class="divide-y-2 divide-dashed"
>
<div
v-for="player in server.players.list"
:key="player.uuid"
class="mb-4 flex items-center gap-4 px-4 pt-4 last:mb-0"
>
<img
:src="`https://minotar.net/helm/${player.uuid}/32.png`"
alt=""
class="h-12 w-12"
>
<p class="text-xl">
{{ player.name }}
</p>
</div>
</div>
<div
v-else
class="text-center"
>
没有在线玩家
</div>
</div>
<div class="mt-4">
<div class="mt-4 flex justify-end gap-4">
<a
href="https://hmcl.huangyuhui.net/"
class="cursor-pointer rounded-lg bg-blue-400 px-4 py-1 text-lg text-white transition-all hover:bg-blue-500"
>
启动器
<font-awesome-icon :icon="['fas', 'arrow-up-right-from-square']" />
</a>
<a class="cursor-pointer rounded-lg bg-blue-400 px-4 py-1 text-lg text-white transition-all hover:bg-blue-500">
整合包
<font-awesome-icon :icon="['fas', 'arrow-up-right-from-square']" />
</a>
<a class="cursor-pointer rounded-lg bg-blue-400 px-4 py-1 text-lg text-white transition-all hover:bg-blue-500">
汉化补丁
<font-awesome-icon :icon="['fas', 'arrow-up-right-from-square']" />
</a>
</div>
</div>
</div>
<div v-else>
<p class="text-center text-xl p-4">
服务器离线
</p>
</div>
</template>
<style scoped>
</style>

View File

@ -1,5 +1,6 @@
<script lang="ts" setup>
import { computed, onMounted, ref } from 'vue'
import McServerStatusCard from '~/components/card/McServerStatusCard.vue'
interface errObj {
blog?: object
@ -9,6 +10,7 @@ interface errObj {
const { $mitt } = useNuxtApp(),
recentPosts = ref<IPost[] | null>(null),
recentActivities = ref<IActivity[] | null>(null),
mcServerStatus = ref<IMCServerStatus | null>(null),
isLoading = ref({
blog: true,
git: true,
@ -34,6 +36,10 @@ const { $mitt } = useNuxtApp(),
'only-performed-by': true,
},
}),
getMCServerStatus = get<IMCServerStatus, unknown>('/frp-now.top:27344', {
baseURL: 'https://api.mcsrvstat.us/3',
timeout: 5000,
}),
hasPosts = computed(() => (recentPosts.value ?? []).length > 0),
hasActivities = computed(() => (recentActivities.value ?? []).length > 0),
@ -89,9 +95,18 @@ const { $mitt } = useNuxtApp(),
finally {
isLoading.value.git = false
}
},
reloadMCServerStatus = async () => {
try {
mcServerStatus.value = await getMCServerStatus()
}
catch (e) {
console.log(e)
}
}
await Promise.allSettled([reloadPosts(), reloadActivities()])
await Promise.allSettled([reloadPosts(), reloadActivities(), reloadMCServerStatus()])
onMounted(() => {
$mitt.emit('startLoading', false)
@ -156,6 +171,27 @@ onMounted(() => {
</template>
</card-section-card>
</section>
<section class="my-4 w-full sm:px-0">
<card-title
title="我的世界"
:icon="['fas', 'gamepad']"
/>
</section>
<card-section-card
:empty="false"
:error="mcServerStatus === null"
:loading="mcServerStatus === null"
:err-msg="undefined"
@reload="reloadMCServerStatus"
>
<template #default>
<div class="w-full rounded-xl bg-white">
<mc-server-status-card :server="mcServerStatus!" />
</div>
</template>
</card-section-card>
</div>
</div>
</template>

View File

@ -16,6 +16,8 @@ import {
faPen,
faXmark,
faBookMedical,
faGamepad,
faArrowUpRightFromSquare,
} from '@fortawesome/free-solid-svg-icons'
import { faClock, faFolder } from '@fortawesome/free-regular-svg-icons'
import { faGithubAlt, faQq, faSteamSymbol, faWeibo } from '@fortawesome/free-brands-svg-icons'
@ -28,6 +30,7 @@ export default defineNuxtPlugin((nuxtApp) => {
library.add(
faClock, faXmark, faBlog, faGauge, faCodeBranch, faCloud, faWeibo, faQq, faGithubAlt, faSteamSymbol, faChevronRight,
faCodeCommit, faCode, faHouse, faPen, faBrush, faChessRook, faBars, faChevronDown, faFolder, faLink, faBookMedical,
faGamepad, faArrowUpRightFromSquare,
)
nuxtApp.vueApp.component('font-awesome-icon', FontAwesomeIcon)

66
types/mc.ts Normal file
View File

@ -0,0 +1,66 @@
declare global {
interface IMCServerStatus {
online: boolean
ip: string
port: number
hostname?: string // Only included when a hostname is detected
debug: { // See section below for information about the values
ping: boolean
query: boolean
srv: boolean
querymismatch: boolean
ipinsrv: boolean
cnameinsrv: boolean
animatedmotd: boolean
cachehit: boolean
cachetime: number
cacheexpire: number
apiversion: number
}
version?: string // Could include multiple versions or additional text
protocol?: { // Only included when ping is used
version: number
name?: string // Only included if a version name is found
}
icon?: string // Only included when an icon is detected
software?: string // Only included when software is detected
map: {
raw: string
clean: string
html: string
}
gamemode?: string // Only included for Bedrock servers
serverid?: string // Only included for Bedrock servers
eula_blocked?: boolean // Only included for Java servers
motd: {
raw: string[]
clean: string[]
html: string[]
}
players: {
online: number
max: number
list?: // Only included when there are players
{
name: string
uuid: string
}[]
}
plugins?: // Only included when plugins are detected
{
name: string
version: string
}[]
mods?: // Only included when mods are detected
{
name: string
version: string
}[]
info?: { // Only included when detecting that the player samples are used for information
raw: string[]
clean: string[]
html: string[]
}
}
}