add time
This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { computed, onUnmounted, ref } from 'vue'
|
||||
import { NAlert, NButton, NCard, NSpace, NTag, useDialog } from 'naive-ui'
|
||||
import type { GameCommand, OnlineIntent, OnlineState } from '../types/online'
|
||||
import { gameCommands, gameStatuses } from '../utils/game-status'
|
||||
import { formatGameDuration } from '../utils/gameDuration'
|
||||
|
||||
const props = defineProps<{
|
||||
state: OnlineState
|
||||
@@ -13,6 +14,12 @@ const props = defineProps<{
|
||||
const emit = defineEmits<{ action: [intent: OnlineIntent] }>()
|
||||
const dialog = useDialog()
|
||||
const game = computed(() => props.state.game?.key === props.selectedKey ? props.state.game : null)
|
||||
const now = ref(Date.now())
|
||||
const duration = computed(() => game.value
|
||||
? formatGameDuration(game.value.startedAt, game.value.endedAt, now.value)
|
||||
: '')
|
||||
const tick = setInterval(() => { now.value = Date.now() }, 1000)
|
||||
onUnmounted(() => clearInterval(tick))
|
||||
const status = computed(() => game.value ? gameStatuses[game.value.status] : null)
|
||||
const disabled = computed(() => props.isBusy || props.state.busy || !props.state.authenticated || !!props.state.gameError)
|
||||
const availableCommands = computed(() => game.value && props.selectedKey ? gameCommands[game.value.status] : [])
|
||||
@@ -52,6 +59,7 @@ function run(command: GameCommand) {
|
||||
<n-tag role="status" data-testid="game-state" :type="state.gameError ? 'warning' : status?.type ?? 'info'">
|
||||
{{ !selectedKey ? 'Игра не выбрана' : status?.label ?? (!state.authenticated ? 'Требуется вход' : state.gameError ? 'Нет данных' : 'Загрузка…') }}
|
||||
</n-tag>
|
||||
<n-tag v-if="game" type="info" data-testid="game-duration">{{ duration }}</n-tag>
|
||||
</div>
|
||||
</template>
|
||||
<template #header-extra>
|
||||
|
||||
+1
-1
@@ -36,7 +36,7 @@ export type OnlineIntent =
|
||||
| { action: 'select-game' | 'download' | 'check'; gameId: number }
|
||||
| { action: 'remove'; key: string }
|
||||
export interface OnlineState {
|
||||
game: { key: string; id: number; name: string; status: GameStatus } | null
|
||||
game: { key: string; id: number; name: string; status: GameStatus; startedAt: string; endedAt: string } | null
|
||||
gameError: string
|
||||
server: string
|
||||
currentGameId: number | null
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
export function formatGameDuration(startedAt: string, endedAt: string, now: number): string {
|
||||
if (!startedAt) return 'Игра ещё не началась'
|
||||
const start = Date.parse(startedAt)
|
||||
// Совместимость с GamePage: серверные TIMESTAMP содержат местные часы как UTC.
|
||||
const localNow = now - new Date(now).getTimezoneOffset() * 60000
|
||||
const end = endedAt ? Date.parse(endedAt) : localNow
|
||||
const diff = end - start
|
||||
if (!Number.isFinite(diff)) return 'Время игры недоступно'
|
||||
if (diff < 0) return 'Игра ещё не началась'
|
||||
|
||||
const seconds = Math.floor(diff / 1000)
|
||||
const minutes = Math.floor(seconds / 60)
|
||||
const hours = Math.floor(minutes / 60)
|
||||
const days = Math.floor(hours / 24)
|
||||
const months = Math.floor(days / 30)
|
||||
const years = Math.floor(days / 365)
|
||||
|
||||
if (years > 0) return `${years}г ${days % 365}д`
|
||||
if (months > 0) return `${months}мес ${days % 30}д`
|
||||
if (days > 0) return `${days}д ${hours % 24}ч`
|
||||
if (hours > 0) return `${hours}ч ${minutes % 60}м`
|
||||
if (minutes > 0) return `${minutes}м ${seconds % 60}с`
|
||||
return `${seconds}с`
|
||||
}
|
||||
Reference in New Issue
Block a user