mirror of
https://github.com/setube/ogame-vue-ts.git
synced 2026-05-12 07:55:11 +08:00
feat: 重构战报弹窗与模拟器视图,优化UI与逻辑
重构BattleReportDialog和BattleSimulatorView相关静态资源,替换旧版JS/CSS文件,提升界面一致性和交互体验。新增和优化空状态、滚动区域等通用UI组件,移除部分冗余composable,完善多语言内容。引入导弹逻辑,补充版本检测工具,提升整体代码结构和可维护性。
This commit is contained in:
@@ -59,6 +59,22 @@
|
||||
<CardDescription>{{ t('settings.gameSettingsDesc') }}</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent class="space-y-4">
|
||||
<!-- 游戏倍率 -->
|
||||
<div class="flex flex-col sm:flex-row items-start sm:items-center justify-between p-4 border rounded-lg gap-3">
|
||||
<div class="space-y-1 flex-1">
|
||||
<h3 class="font-medium">{{ t('settings.gameSpeed') }}</h3>
|
||||
<p class="text-sm text-muted-foreground">{{ t('settings.gameSpeedDesc') }}</p>
|
||||
</div>
|
||||
<div class="flex items-center gap-2 sm:gap-4 w-full sm:w-auto">
|
||||
<div class="flex items-center gap-2 flex-1 sm:flex-initial">
|
||||
<Button @click="decreaseSpeed" variant="outline" size="sm" :disabled="gameStore.gameSpeed <= 0.5">-</Button>
|
||||
<span class="min-w-[60px] text-center font-medium">{{ gameStore.gameSpeed || 1 }}x</span>
|
||||
<Button @click="increaseSpeed" variant="outline" size="sm" :disabled="gameStore.gameSpeed >= 10">+</Button>
|
||||
</div>
|
||||
<Button @click="resetSpeed" variant="ghost" size="sm">{{ t('settings.reset') }}</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 游戏暂停 -->
|
||||
<div class="flex items-center justify-between p-4 border rounded-lg">
|
||||
<div class="space-y-1">
|
||||
@@ -88,6 +104,15 @@
|
||||
<span class="text-muted-foreground">{{ t('settings.buildDate') }}:</span>
|
||||
<span class="font-medium">{{ pkg.buildDate }}</span>
|
||||
</div>
|
||||
<!-- 检查更新按钮 -->
|
||||
<div class="pt-2">
|
||||
<Button @click="handleCheckVersion" variant="outline" size="sm" :disabled="isCheckingVersion || !canCheck" class="w-full">
|
||||
<RefreshCw class="mr-2 h-4 w-4" :class="{ 'animate-spin': isCheckingVersion }" />
|
||||
<template v-if="isCheckingVersion">{{ t('settings.checking') }}</template>
|
||||
<template v-else-if="!canCheck && cooldownTime">{{ cooldownTime }}</template>
|
||||
<template v-else>{{ t('settings.checkUpdate') }}</template>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 社区链接 -->
|
||||
@@ -127,11 +152,14 @@
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
|
||||
<!-- 更新对话框 -->
|
||||
<UpdateDialog v-model:open="showUpdateDialog" :version-info="updateInfo" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { ref, computed, onMounted, onUnmounted } from 'vue'
|
||||
import { useGameStore } from '@/stores/gameStore'
|
||||
import { useI18n } from '@/composables/useI18n'
|
||||
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@/components/ui/card'
|
||||
@@ -146,23 +174,64 @@
|
||||
AlertDialogHeader,
|
||||
AlertDialogTitle
|
||||
} from '@/components/ui/alert-dialog'
|
||||
import { Download, Upload, Trash2, ExternalLink, MessagesSquare, Play, Pause } from 'lucide-vue-next'
|
||||
import { Download, Upload, Trash2, ExternalLink, MessagesSquare, Play, Pause, RefreshCw } from 'lucide-vue-next'
|
||||
import { saveAs } from 'file-saver'
|
||||
import { toast } from 'vue-sonner'
|
||||
import pkg from '../../package.json'
|
||||
import 'vue-sonner/style.css'
|
||||
import { checkLatestVersion, canCheckVersion } from '@/utils/versionCheck'
|
||||
import type { VersionInfo } from '@/utils/versionCheck'
|
||||
import UpdateDialog from '@/components/UpdateDialog.vue'
|
||||
|
||||
const { t } = useI18n()
|
||||
const gameStore = useGameStore()
|
||||
|
||||
const fileInputRef = ref<HTMLInputElement>()
|
||||
const isExporting = ref(false)
|
||||
const isCheckingVersion = ref(false)
|
||||
const cooldownTime = ref('')
|
||||
|
||||
const showConfirmDialog = ref(false)
|
||||
const confirmTitle = ref('')
|
||||
const confirmMessage = ref('')
|
||||
let confirmCallback: (() => void) | null = null
|
||||
|
||||
// 计算是否可以检查版本(主动检测:5分钟内不能重复检查)
|
||||
const canCheck = computed(() => canCheckVersion(gameStore.player.lastManualUpdateCheck || 0))
|
||||
|
||||
// 计算剩余冷却时间
|
||||
const updateCooldownTime = () => {
|
||||
if (canCheck.value) {
|
||||
cooldownTime.value = ''
|
||||
return
|
||||
}
|
||||
|
||||
const lastCheck = gameStore.player.lastManualUpdateCheck || 0
|
||||
const now = Date.now()
|
||||
const fiveMinutes = 5 * 60 * 1000
|
||||
const timePassed = now - lastCheck
|
||||
const timeRemaining = fiveMinutes - timePassed
|
||||
|
||||
if (timeRemaining <= 0) {
|
||||
cooldownTime.value = ''
|
||||
return
|
||||
}
|
||||
|
||||
const minutes = Math.floor(timeRemaining / 60000)
|
||||
const seconds = Math.floor((timeRemaining % 60000) / 1000)
|
||||
cooldownTime.value = `${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}`
|
||||
}
|
||||
|
||||
// 每秒更新倒计时
|
||||
let cooldownInterval: ReturnType<typeof setInterval> | null = null
|
||||
onMounted(() => {
|
||||
updateCooldownTime()
|
||||
cooldownInterval = setInterval(updateCooldownTime, 1000)
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
if (cooldownInterval) clearInterval(cooldownInterval)
|
||||
})
|
||||
|
||||
const openGithub = () => {
|
||||
window.open(`https://github.com/${pkg.author.name}/${pkg.name}`, '_blank')
|
||||
}
|
||||
@@ -171,6 +240,32 @@
|
||||
window.open(`https://qm.qq.com/q/${pkg.id}`, '_blank')
|
||||
}
|
||||
|
||||
// 手动检查版本
|
||||
const showUpdateDialog = ref(false)
|
||||
const updateInfo = ref<VersionInfo | null>(null)
|
||||
|
||||
const handleCheckVersion = async () => {
|
||||
if (isCheckingVersion.value || !canCheck.value) return
|
||||
|
||||
isCheckingVersion.value = true
|
||||
try {
|
||||
const versionInfo = await checkLatestVersion(gameStore.player.lastManualUpdateCheck || 0, (time: number) => {
|
||||
gameStore.player.lastManualUpdateCheck = time
|
||||
})
|
||||
if (versionInfo) {
|
||||
updateInfo.value = versionInfo
|
||||
showUpdateDialog.value = true
|
||||
} else {
|
||||
toast.success(t('settings.upToDate'))
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to check for updates:', error)
|
||||
toast.error(t('settings.checkUpdateFailed'))
|
||||
} finally {
|
||||
isCheckingVersion.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 导出数据(包含游戏数据和地图数据)
|
||||
const handleExport = async () => {
|
||||
try {
|
||||
@@ -281,10 +376,37 @@
|
||||
}
|
||||
|
||||
const clearData = () => {
|
||||
// 清除localStorage
|
||||
localStorage.clear()
|
||||
// 重新加载页面
|
||||
window.location.reload()
|
||||
gameStore.isPaused = true
|
||||
try {
|
||||
localStorage.clear()
|
||||
window.location.reload()
|
||||
} catch (error) {
|
||||
console.error('Failed to clear data:', error)
|
||||
// 即使出错也尝试重新加载
|
||||
window.location.reload()
|
||||
}
|
||||
}
|
||||
|
||||
// 增加游戏倍率
|
||||
const increaseSpeed = () => {
|
||||
if (gameStore.gameSpeed < 10) {
|
||||
gameStore.gameSpeed = Math.min(10, gameStore.gameSpeed + 0.5)
|
||||
toast.success(t('settings.speedChanged', { speed: gameStore.gameSpeed }))
|
||||
}
|
||||
}
|
||||
|
||||
// 减少游戏倍率
|
||||
const decreaseSpeed = () => {
|
||||
if (gameStore.gameSpeed > 0.5) {
|
||||
gameStore.gameSpeed = Math.max(0.5, gameStore.gameSpeed - 0.5)
|
||||
toast.success(t('settings.speedChanged', { speed: gameStore.gameSpeed }))
|
||||
}
|
||||
}
|
||||
|
||||
// 重置游戏倍率
|
||||
const resetSpeed = () => {
|
||||
gameStore.gameSpeed = 1
|
||||
toast.success(t('settings.speedReset'))
|
||||
}
|
||||
|
||||
// 切换游戏暂停状态
|
||||
|
||||
Reference in New Issue
Block a user