refactor: 优化主界面布局与通知系统

重构App.vue,首页独立无侧边栏,其他页面采用统一侧边栏布局。新增右下角固定通知区,集成返回顶部、队列通知、外交通知和敌方警报。移除新手引导组件,替换为弱引导提示系统。支持星球重命名弹窗。优化NPC成长与行为定时器逻辑,提升性能和可维护性。删除issue模板及相关文档描述。
This commit is contained in:
谦君
2025-12-19 12:01:45 +08:00
parent a689ce21b7
commit 752cade67c
61 changed files with 5774 additions and 2817 deletions

View File

@@ -205,16 +205,30 @@
<div v-if="slot.planet" class="space-y-1">
<!-- 第一行:名称、坐标、状态、残骸 -->
<div class="flex items-center gap-1.5 min-w-0 flex-wrap">
<h3 class="font-semibold text-sm truncate">{{ slot.planet.name }}</h3>
<h3 class="font-semibold text-sm truncate">
{{ isMyPlanet(slot.planet) ? slot.planet.name : getNpcPlanetDisplayName(slot.planet) }}
</h3>
<span class="text-xs text-muted-foreground whitespace-nowrap flex-shrink-0">
[{{ slot.planet.position.galaxy }}:{{ slot.planet.position.system }}:{{ slot.planet.position.position }}]
</span>
<Badge v-if="isMyPlanet(slot.planet)" variant="default" class="text-xs flex-shrink-0">
{{ t('galaxyView.mine') }}
</Badge>
<Badge v-else :variant="getRelationBadgeVariant(slot.planet)" class="text-xs flex-shrink-0">
{{ getRelationStatusText(slot.planet) }}
</Badge>
<Popover v-else>
<PopoverTrigger as-child>
<Badge :variant="getRelationBadgeVariant(slot.planet)" class="text-xs flex-shrink-0 cursor-pointer">
{{ getRelationStatusText(slot.planet) }}
</Badge>
</PopoverTrigger>
<PopoverContent v-if="getReputationValue(slot.planet) !== null" class="w-auto p-3" side="top" align="center">
<p class="text-sm">
{{ t('diplomacy.reputation') }}:
<span :class="getReputationColor(getReputationValue(slot.planet))" class="font-medium">
{{ getReputationValue(slot.planet)! > 0 ? '+' : '' }}{{ getReputationValue(slot.planet) }}
</span>
</p>
</PopoverContent>
</Popover>
<Popover v-if="getDebrisFieldAt(currentGalaxy, currentSystem, slot.position)">
<PopoverTrigger as-child>
<Badge
@@ -224,7 +238,7 @@
<Recycle class="h-3 w-3" />
</Badge>
</PopoverTrigger>
<PopoverContent class="w-auto p-3" side="top" align="start">
<PopoverContent class="w-auto p-3" side="top" align="center">
<div class="space-y-2">
<p class="text-xs font-semibold text-amber-700 dark:text-amber-400">{{ t('galaxyView.debrisField') }}</p>
<div class="space-y-1 text-xs">
@@ -247,13 +261,6 @@
</PopoverContent>
</Popover>
</div>
<!-- 第二行:好感度 -->
<div v-if="!isMyPlanet(slot.planet) && getReputationValue(slot.planet) !== null" class="text-xs">
<span class="text-muted-foreground">{{ t('diplomacy.reputation') }}:</span>
<span class="ml-1 font-semibold" :class="getReputationColor(getReputationValue(slot.planet))">
{{ getReputationValue(slot.planet)! > 0 ? '+' : '' }}{{ getReputationValue(slot.planet) }}
</span>
</div>
</div>
<!-- 空位置 -->
<div v-else class="space-y-1">
@@ -389,11 +396,27 @@
<div v-if="slot.planet" class="space-y-1">
<!-- PC端标题和徽章 -->
<div class="flex items-center gap-2 flex-wrap">
<h3 class="font-semibold text-base">{{ slot.planet.name }}</h3>
<h3 class="font-semibold text-base">
{{ isMyPlanet(slot.planet) ? slot.planet.name : getNpcPlanetDisplayName(slot.planet) }}
</h3>
<Badge v-if="isMyPlanet(slot.planet)" variant="default" class="text-xs">{{ t('galaxyView.mine') }}</Badge>
<Badge v-else :variant="getRelationBadgeVariant(slot.planet)" class="text-xs">
{{ getRelationStatusText(slot.planet) }}
</Badge>
<TooltipProvider v-else :delay-duration="300">
<Tooltip>
<TooltipTrigger as-child>
<Badge :variant="getRelationBadgeVariant(slot.planet)" class="text-xs cursor-default">
{{ getRelationStatusText(slot.planet) }}
</Badge>
</TooltipTrigger>
<TooltipContent v-if="getReputationValue(slot.planet) !== null">
<p>
{{ t('diplomacy.reputation') }}:
<span :class="getReputationColor(getReputationValue(slot.planet))">
{{ getReputationValue(slot.planet)! > 0 ? '+' : '' }}{{ getReputationValue(slot.planet) }}
</span>
</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
<!-- 残骸场徽章 -->
<Popover v-if="getDebrisFieldAt(currentGalaxy, currentSystem, slot.position)">
<PopoverTrigger as-child>
@@ -432,13 +455,6 @@
<p class="text-xs text-muted-foreground">
[{{ slot.planet.position.galaxy }}:{{ slot.planet.position.system }}:{{ slot.planet.position.position }}]
</p>
<!-- PC端好感度显示仅NPC星球 -->
<div v-if="!isMyPlanet(slot.planet) && getReputationValue(slot.planet) !== null" class="text-xs">
<span class="text-muted-foreground">{{ t('diplomacy.reputation') }}:</span>
<span class="ml-1 font-semibold" :class="getReputationColor(getReputationValue(slot.planet))">
{{ getReputationValue(slot.planet)! > 0 ? '+' : '' }}{{ getReputationValue(slot.planet) }}
</span>
</div>
</div>
<!-- 空位置 -->
<div v-else class="space-y-1">
@@ -744,9 +760,6 @@
selectedGalaxy.value = queryGalaxy
selectedSystem.value = querySystem
loadSystem()
// 立即清除URL参数但保持本地变量中的highlightNpcId
clearUrlParams()
} else if (gameStore.currentPlanet) {
// 否则默认显示当前星球所在的星系
currentGalaxy.value = gameStore.currentPlanet.position.galaxy
@@ -778,13 +791,6 @@
return universeStore.debrisFields[debrisId] || null
}
// 清除URL参数
const clearUrlParams = () => {
if (route.query.highlightNpc || route.query.galaxy || route.query.system) {
router.replace({ query: {} })
}
}
// 加载星系
const loadSystem = () => {
currentGalaxy.value = selectedGalaxy.value
@@ -833,7 +839,8 @@
const getRelation = (planet: Planet | null) => {
const npc = getPlanetNPC(planet)
if (!npc) return null
return gameStore.player.diplomaticRelations?.[npc.id]
// 从NPC的relations中获取对玩家的关系
return npc.relations?.[gameStore.player.id]
}
// 获取关系状态Badge样式
@@ -880,6 +887,17 @@
return 'text-muted-foreground'
}
// 获取NPC星球的显示名称 - 使用"XXX的星球"格式,如果有备注则显示"NPC名称(备注)的星球"
const getNpcPlanetDisplayName = (planet: Planet | null): string => {
if (!planet) return ''
const npc = getPlanetNPC(planet)
if (npc) {
const displayName = npc.note ? `${npc.name}(${npc.note})` : npc.name
return t('galaxyView.npcPlanetName').replace('{name}', displayName)
}
return planet.name
}
// 切换到指定星球
const switchToPlanet = (planetId: string) => {
gameStore.currentPlanetId = planetId