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

@@ -11,7 +11,10 @@
</div>
<div class="grid grid-cols-2 lg:grid-cols-3 gap-3 sm:gap-4">
<Card v-for="buildingType in availableBuildings" :key="buildingType">
<Card v-for="buildingType in availableBuildings" :key="buildingType" class="relative">
<!-- 前置条件遮罩 -->
<CardUnlockOverlay :requirements="BUILDINGS[buildingType].requirements" :currentLevel="getBuildingLevel(buildingType)" />
<CardHeader>
<div class="flex justify-between items-start gap-2">
<div class="min-w-0 flex-1">
@@ -89,7 +92,7 @@
<!-- 升级按钮 -->
<Button @click="handleUpgrade(buildingType)" :disabled="!canUpgrade(buildingType)" class="w-full">
{{ t('buildingsView.upgrade') }}
{{ getUpgradeButtonText(buildingType) }}
</Button>
<!-- 拆除按钮 -->
@@ -128,22 +131,24 @@
import { useI18n } from '@/composables/useI18n'
import { useGameConfig } from '@/composables/useGameConfig'
import { computed, ref } from 'vue'
import { BuildingType } from '@/types/game'
import { BuildingType, TechnologyType } from '@/types/game'
import type { Resources, Planet } from '@/types/game'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { Button } from '@/components/ui/button'
import { Badge } from '@/components/ui/badge'
import ResourceIcon from '@/components/ResourceIcon.vue'
import CardUnlockOverlay from '@/components/CardUnlockOverlay.vue'
import AlertDialog from '@/components/AlertDialog.vue'
import { Clock, Grid3x3 } from 'lucide-vue-next'
import { formatNumber, formatTime, getResourceCostColor } from '@/utils/format'
import * as buildingLogic from '@/logic/buildingLogic'
import * as buildingValidation from '@/logic/buildingValidation'
import * as publicLogic from '@/logic/publicLogic'
const gameStore = useGameStore()
const detailDialog = useDetailDialogStore()
const { t } = useI18n()
const { BUILDINGS } = useGameConfig()
const { BUILDINGS, TECHNOLOGIES } = useGameConfig()
const planet = computed(() => gameStore.currentPlanet)
const alertDialog = ref<InstanceType<typeof AlertDialog> | null>(null)
@@ -182,6 +187,15 @@
// 升级建筑
const handleUpgrade = (buildingType: BuildingType) => {
// 检查前置条件
if (!checkUpgradeRequirements(buildingType)) {
alertDialog.value?.show({
title: t('common.requirementsNotMet'),
message: getRequirementsList(buildingType)
})
return
}
const success = upgradeBuilding(buildingType)
if (!success) {
alertDialog.value?.show({
@@ -196,12 +210,98 @@
return planet.value?.buildings[buildingType] || 0
}
// 检查升级前置条件是否满足
const checkUpgradeRequirements = (buildingType: BuildingType): boolean => {
if (!planet.value) return false
const config = BUILDINGS.value[buildingType]
const currentLevel = getBuildingLevel(buildingType)
const targetLevel = currentLevel + 1
// 获取目标等级的所有前置条件(包括等级门槛)
const requirements = publicLogic.getLevelRequirements(config, targetLevel)
if (!requirements || Object.keys(requirements).length === 0) return true
return publicLogic.checkRequirements(planet.value, gameStore.player.technologies, requirements)
}
// 获取升级按钮文本
const getUpgradeButtonText = (buildingType: BuildingType): string => {
if (!planet.value) return t('buildingsView.upgrade')
const config = BUILDINGS.value[buildingType]
const currentLevel = getBuildingLevel(buildingType)
// 检查是否达到等级上限
if (config.maxLevel !== undefined && currentLevel >= config.maxLevel) {
return t('buildingsView.maxLevelReached') // "等级已满"
}
if (planet.value.buildQueue.length > 0) return t('buildingsView.upgrade')
// 检查前置条件
if (!checkUpgradeRequirements(buildingType)) {
return t('buildingsView.requirementsNotMet')
}
return t('buildingsView.upgrade')
}
// 获取前置条件列表文本
const getRequirementsList = (buildingType: BuildingType): string => {
const config = BUILDINGS.value[buildingType]
const currentLevel = getBuildingLevel(buildingType)
const targetLevel = currentLevel + 1
// 获取目标等级的所有前置条件(包括等级门槛)
const requirements = publicLogic.getLevelRequirements(config, targetLevel)
if (!requirements || !planet.value) return ''
const lines: string[] = []
for (const [key, requiredLevel] of Object.entries(requirements)) {
// 检查是否为建筑类型
if (Object.values(BuildingType).includes(key as BuildingType)) {
const bt = key as BuildingType
const currentLevel = planet.value.buildings[bt] || 0
const name = BUILDINGS.value[bt]?.name || bt
const status = currentLevel >= requiredLevel ? '✓' : '✗'
lines.push(`${status} ${name}: Lv ${requiredLevel} (${t('common.current')}: Lv ${currentLevel})`)
}
// 检查是否为科技类型
else if (Object.values(TechnologyType).includes(key as TechnologyType)) {
const tt = key as TechnologyType
const currentLevel = gameStore.player.technologies[tt] || 0
const name = TECHNOLOGIES.value[tt]?.name || tt
const status = currentLevel >= requiredLevel ? '✓' : '✗'
lines.push(`${status} ${name}: Lv ${requiredLevel} (${t('common.current')}: Lv ${currentLevel})`)
}
}
return lines.join('\n')
}
// 检查是否可以升级
const canUpgrade = (buildingType: BuildingType): boolean => {
if (!planet.value) return false
const config = BUILDINGS.value[buildingType]
const currentLevel = getBuildingLevel(buildingType)
// 检查是否达到等级上限
if (config.maxLevel !== undefined && currentLevel >= config.maxLevel) {
return false
}
if (planet.value.buildQueue.length > 0) return false
const currentLevel = getBuildingLevel(buildingType)
// 检查前置条件
const validation = buildingValidation.validateBuildingUpgrade(
planet.value,
buildingType,
gameStore.player.technologies,
gameStore.player.officers
)
if (!validation.valid) return false
const cost = getBuildingCost(buildingType, currentLevel + 1)
return (