feat: 新增战报弹窗与舰队模拟器,重构UI组件

新增 BattleReportDialog、SpyReportDialog、NumberWithTooltip 等组件,完善舰队模拟器功能。重构并引入 Sheet、Sidebar、Tooltip、Skeleton 等 UI 组件,优化界面结构。实现 battle.worker 支持战斗计算,增加 universeStore、fleetStorageLogic 等核心逻辑,完善多语言与类型定义。
This commit is contained in:
谦君
2025-12-13 11:14:23 +08:00
parent 8637e50115
commit 731d79673b
160 changed files with 6302 additions and 1931 deletions

View File

@@ -10,7 +10,9 @@
</CardTitle>
</CardHeader>
<CardContent>
<div class="text-2xl font-bold">{{ formatNumber(config.attack) }}</div>
<div class="text-2xl font-bold">
<NumberWithTooltip :value="config.attack" />
</div>
</CardContent>
</Card>
@@ -22,7 +24,9 @@
</CardTitle>
</CardHeader>
<CardContent>
<div class="text-2xl font-bold">{{ formatNumber(config.shield) }}</div>
<div class="text-2xl font-bold">
<NumberWithTooltip :value="config.shield" />
</div>
</CardContent>
</Card>
@@ -34,7 +38,9 @@
</CardTitle>
</CardHeader>
<CardContent>
<div class="text-2xl font-bold">{{ formatNumber(config.armor) }}</div>
<div class="text-2xl font-bold">
<NumberWithTooltip :value="config.armor" />
</div>
</CardContent>
</Card>
</div>
@@ -48,19 +54,27 @@
<CardContent class="space-y-2">
<div v-if="config.cost.metal > 0" class="flex items-center justify-between text-sm">
<span class="text-muted-foreground">{{ t('resources.metal') }}:</span>
<span class="font-medium">{{ formatNumber(config.cost.metal) }}</span>
<span class="font-medium">
<NumberWithTooltip :value="config.cost.metal" />
</span>
</div>
<div v-if="config.cost.crystal > 0" class="flex items-center justify-between text-sm">
<span class="text-muted-foreground">{{ t('resources.crystal') }}:</span>
<span class="font-medium">{{ formatNumber(config.cost.crystal) }}</span>
<span class="font-medium">
<NumberWithTooltip :value="config.cost.crystal" />
</span>
</div>
<div v-if="config.cost.deuterium > 0" class="flex items-center justify-between text-sm">
<span class="text-muted-foreground">{{ t('resources.deuterium') }}:</span>
<span class="font-medium">{{ formatNumber(config.cost.deuterium) }}</span>
<span class="font-medium">
<NumberWithTooltip :value="config.cost.deuterium" />
</span>
</div>
<div class="flex items-center justify-between text-sm pt-2 border-t">
<span class="text-muted-foreground">{{ t('player.points') }}:</span>
<span class="font-bold text-primary">{{ pointsPerUnit }}</span>
<span class="font-bold text-primary">
<NumberWithTooltip :value="pointsPerUnit" />
</span>
</div>
</CardContent>
</Card>
@@ -92,22 +106,31 @@
<div class="space-y-1 text-sm">
<div class="flex justify-between">
<span>{{ t('resources.metal') }}:</span>
<span class="font-medium">{{ formatNumber(batchCost.metal) }}</span>
<span class="font-medium">
<NumberWithTooltip :value="batchCost.metal" />
</span>
</div>
<div class="flex justify-between">
<span>{{ t('resources.crystal') }}:</span>
<span class="font-medium">{{ formatNumber(batchCost.crystal) }}</span>
<span class="font-medium">
<NumberWithTooltip :value="batchCost.crystal" />
</span>
</div>
<div class="flex justify-between">
<span>{{ t('resources.deuterium') }}:</span>
<span class="font-medium">{{ formatNumber(batchCost.deuterium) }}</span>
<span class="font-medium">
<NumberWithTooltip :value="batchCost.deuterium" />
</span>
</div>
</div>
</div>
<div class="space-y-2">
<p class="text-sm text-muted-foreground">{{ t('defense.totalTime') }}:</p>
<div class="text-xl font-bold">{{ formatTime(config.buildTime * quantity) }}</div>
<p class="text-xs text-muted-foreground">{{ t('player.points') }}: +{{ formatNumber(batchPoints) }}</p>
<p class="text-xs text-muted-foreground">
{{ t('player.points') }}: +
<NumberWithTooltip :value="batchPoints" />
</p>
</div>
</div>
</CardContent>
@@ -122,9 +145,11 @@
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
import NumberWithTooltip from '@/components/NumberWithTooltip.vue'
import { Sword, Shield, ShieldCheck } from 'lucide-vue-next'
import * as pointsLogic from '@/logic/pointsLogic'
import { DEFENSES } from '@/config/gameConfig'
import { formatTime } from '@/utils/format'
const { t } = useI18n()
@@ -151,18 +176,4 @@
const batchPoints = computed(() => {
return pointsLogic.calculateDefensePoints(props.defenseType, quantity.value)
})
const formatNumber = (num: number): string => {
return num.toLocaleString()
}
const formatTime = (seconds: number): string => {
if (seconds < 60) return `${seconds}${t('common.timeSecond')}`
const minutes = Math.floor(seconds / 60)
const secs = seconds % 60
if (minutes < 60) return `${minutes}${t('common.timeMinute')}${secs}${t('common.timeSecond')}`
const hours = Math.floor(minutes / 60)
const mins = minutes % 60
return `${hours}${t('common.timeHour')}${mins}${t('common.timeMinute')}`
}
</script>