mirror of
https://github.com/setube/ogame-vue-ts.git
synced 2026-05-12 07:55:11 +08:00
fix: 修复重复星球 ID 并优化 NPC 列表排序性能
修复玩家星球重复 ID 问题,通过构建映射关系更新相关引用(舰队任务、间谍报告等),避免数据指向错误目标。同时优化外交界面 NPC 列表计算,避免重复排序操作提升性能,并添加空列表检查防止除零错误。
This commit is contained in:
@@ -1,4 +1,18 @@
|
|||||||
import type { Planet, DebrisField, NPC } from '@/types/game'
|
import type {
|
||||||
|
AllyDefenseNotification,
|
||||||
|
DebrisField,
|
||||||
|
FleetMission,
|
||||||
|
IncomingFleetAlert,
|
||||||
|
JointAttackInvite,
|
||||||
|
MissionReport,
|
||||||
|
NPC,
|
||||||
|
NPCActivityNotification,
|
||||||
|
Planet,
|
||||||
|
Player,
|
||||||
|
Position,
|
||||||
|
SpiedNotification,
|
||||||
|
SpyReport
|
||||||
|
} from '@/types/game'
|
||||||
import { decryptData, encryptData } from './crypto'
|
import { decryptData, encryptData } from './crypto'
|
||||||
import { generatePlanetTemperature } from '@/logic/planetLogic'
|
import { generatePlanetTemperature } from '@/logic/planetLogic'
|
||||||
import pkg from '../../package.json'
|
import pkg from '../../package.json'
|
||||||
@@ -8,6 +22,378 @@ import pkg from '../../package.json'
|
|||||||
* 用于从旧版本数据结构迁移到新版本
|
* 用于从旧版本数据结构迁移到新版本
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
type PlanetKind = 'planet' | 'moon'
|
||||||
|
|
||||||
|
// oldPlanetId -> position -> planet/moon -> remapped target
|
||||||
|
type DuplicatePlanetIdMap = Map<
|
||||||
|
string,
|
||||||
|
Map<string, Map<PlanetKind, { newId: string; name: string }>>
|
||||||
|
>
|
||||||
|
|
||||||
|
interface MigratablePlayer extends Player {
|
||||||
|
diplomaticRelations?: Record<string, unknown>
|
||||||
|
}
|
||||||
|
|
||||||
|
interface MigratableGameData {
|
||||||
|
currentPlanetId?: string
|
||||||
|
player?: MigratablePlayer
|
||||||
|
npcs?: NPC[]
|
||||||
|
universePlanets?: Record<string, Planet>
|
||||||
|
debrisFields?: Record<string, DebrisField>
|
||||||
|
}
|
||||||
|
|
||||||
|
interface PlanetReferenceContext {
|
||||||
|
position?: Position
|
||||||
|
isMoon?: boolean
|
||||||
|
planetName?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const getPlanetPositionKey = (position: Position): string => {
|
||||||
|
return `${position.galaxy}:${position.system}:${position.position}`
|
||||||
|
}
|
||||||
|
|
||||||
|
const getPlanetKindKey = (isMoon?: boolean): PlanetKind => {
|
||||||
|
return isMoon ? 'moon' : 'planet'
|
||||||
|
}
|
||||||
|
|
||||||
|
const buildDuplicatePlanetIdMap = (player: Player): DuplicatePlanetIdMap => {
|
||||||
|
const planetsByOriginalId = new Map<string, Planet[]>()
|
||||||
|
|
||||||
|
player.planets.forEach(planet => {
|
||||||
|
let group = planetsByOriginalId.get(planet.id)
|
||||||
|
if (!group) {
|
||||||
|
group = []
|
||||||
|
planetsByOriginalId.set(planet.id, group)
|
||||||
|
}
|
||||||
|
group.push(planet)
|
||||||
|
})
|
||||||
|
|
||||||
|
const idMap: DuplicatePlanetIdMap = new Map()
|
||||||
|
|
||||||
|
planetsByOriginalId.forEach((planets, originalId) => {
|
||||||
|
if (planets.length <= 1) return
|
||||||
|
|
||||||
|
planets.forEach((planet, index) => {
|
||||||
|
if (index === 0) return
|
||||||
|
|
||||||
|
const newId = `${originalId}_${Math.random().toString(36).substring(2, 9)}`
|
||||||
|
const positionKey = getPlanetPositionKey(planet.position)
|
||||||
|
|
||||||
|
let byPosition = idMap.get(originalId)
|
||||||
|
if (!byPosition) {
|
||||||
|
byPosition = new Map()
|
||||||
|
idMap.set(originalId, byPosition)
|
||||||
|
}
|
||||||
|
|
||||||
|
let byKind = byPosition.get(positionKey)
|
||||||
|
if (!byKind) {
|
||||||
|
byKind = new Map()
|
||||||
|
byPosition.set(positionKey, byKind)
|
||||||
|
}
|
||||||
|
|
||||||
|
byKind.set(getPlanetKindKey(planet.isMoon), {
|
||||||
|
newId,
|
||||||
|
name: planet.name
|
||||||
|
})
|
||||||
|
|
||||||
|
planet.id = newId
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
return idMap
|
||||||
|
}
|
||||||
|
|
||||||
|
const resolveRemappedPlanetId = (
|
||||||
|
planetId: string | undefined,
|
||||||
|
idMap: DuplicatePlanetIdMap,
|
||||||
|
context: PlanetReferenceContext = {}
|
||||||
|
): string | undefined => {
|
||||||
|
if (!planetId) return undefined
|
||||||
|
|
||||||
|
const byPosition = idMap.get(planetId)
|
||||||
|
if (!byPosition) return undefined
|
||||||
|
|
||||||
|
if (context.position) {
|
||||||
|
const byKind = byPosition.get(getPlanetPositionKey(context.position))
|
||||||
|
if (!byKind) return undefined
|
||||||
|
|
||||||
|
// 只有在位置或名称足够区分目标时才重写引用,避免把旧引用误指到错误星球
|
||||||
|
if (context.isMoon !== undefined) {
|
||||||
|
return byKind.get(getPlanetKindKey(context.isMoon))?.newId
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context.planetName) {
|
||||||
|
const matchedByName = Array.from(byKind.values()).filter(entry => entry.name === context.planetName)
|
||||||
|
if (matchedByName.length === 1) {
|
||||||
|
const [matchedEntry] = matchedByName
|
||||||
|
if (matchedEntry) {
|
||||||
|
return matchedEntry.newId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (byKind.size === 1) {
|
||||||
|
return Array.from(byKind.values())[0]?.newId
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context.planetName) {
|
||||||
|
const matchedByName: Array<{ newId: string; name: string }> = []
|
||||||
|
|
||||||
|
byPosition.forEach(byKind => {
|
||||||
|
byKind.forEach(entry => {
|
||||||
|
if (entry.name === context.planetName) {
|
||||||
|
matchedByName.push(entry)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
if (matchedByName.length === 1) {
|
||||||
|
const [matchedEntry] = matchedByName
|
||||||
|
if (matchedEntry) {
|
||||||
|
return matchedEntry.newId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
const updatePlanetIdField = <
|
||||||
|
T extends Record<string, unknown>,
|
||||||
|
K extends keyof T
|
||||||
|
>(
|
||||||
|
target: T,
|
||||||
|
key: K,
|
||||||
|
idMap: DuplicatePlanetIdMap,
|
||||||
|
context: PlanetReferenceContext = {}
|
||||||
|
): boolean => {
|
||||||
|
const currentValue = target[key]
|
||||||
|
if (typeof currentValue !== 'string') return false
|
||||||
|
|
||||||
|
const remappedPlanetId = resolveRemappedPlanetId(currentValue, idMap, context)
|
||||||
|
if (!remappedPlanetId || remappedPlanetId === currentValue) return false
|
||||||
|
|
||||||
|
target[key] = remappedPlanetId as T[K]
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateMissionTargetPlanetId = (mission: FleetMission, idMap: DuplicatePlanetIdMap): boolean => {
|
||||||
|
return updatePlanetIdField(mission as unknown as Record<string, unknown>, 'targetPlanetId', idMap, {
|
||||||
|
position: mission.targetPosition,
|
||||||
|
isMoon: mission.targetIsMoon
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateSpyReportTargetPlanetId = (report: SpyReport, idMap: DuplicatePlanetIdMap): boolean => {
|
||||||
|
return updatePlanetIdField(report as unknown as Record<string, unknown>, 'targetPlanetId', idMap, {
|
||||||
|
position: report.targetPosition,
|
||||||
|
planetName: report.targetPlanetName
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateSpiedNotificationTargetPlanetId = (
|
||||||
|
notification: SpiedNotification,
|
||||||
|
idMap: DuplicatePlanetIdMap
|
||||||
|
): boolean => {
|
||||||
|
return updatePlanetIdField(notification as unknown as Record<string, unknown>, 'targetPlanetId', idMap, {
|
||||||
|
planetName: notification.targetPlanetName
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateNPCActivityTargetPlanetId = (
|
||||||
|
notification: NPCActivityNotification,
|
||||||
|
idMap: DuplicatePlanetIdMap
|
||||||
|
): boolean => {
|
||||||
|
return updatePlanetIdField(notification as unknown as Record<string, unknown>, 'targetPlanetId', idMap, {
|
||||||
|
position: notification.targetPosition,
|
||||||
|
planetName: notification.targetPlanetName
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateIncomingAlertTargetPlanetId = (
|
||||||
|
alert: IncomingFleetAlert,
|
||||||
|
idMap: DuplicatePlanetIdMap
|
||||||
|
): boolean => {
|
||||||
|
return updatePlanetIdField(alert as unknown as Record<string, unknown>, 'targetPlanetId', idMap, {
|
||||||
|
planetName: alert.targetPlanetName
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateJointAttackTargetPlanetId = (
|
||||||
|
invite: JointAttackInvite,
|
||||||
|
idMap: DuplicatePlanetIdMap
|
||||||
|
): boolean => {
|
||||||
|
return updatePlanetIdField(invite as unknown as Record<string, unknown>, 'targetPlanetId', idMap, {
|
||||||
|
position: invite.targetPosition
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateAllyDefenseTargetPlanetId = (
|
||||||
|
notification: AllyDefenseNotification,
|
||||||
|
idMap: DuplicatePlanetIdMap
|
||||||
|
): boolean => {
|
||||||
|
return updatePlanetIdField(notification as unknown as Record<string, unknown>, 'targetPlanetId', idMap, {
|
||||||
|
planetName: notification.targetPlanetName
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateMissionReportPlanetIds = (report: MissionReport, idMap: DuplicatePlanetIdMap): boolean => {
|
||||||
|
let mutated = false
|
||||||
|
|
||||||
|
if (updatePlanetIdField(report as unknown as Record<string, unknown>, 'originPlanetId', idMap, {
|
||||||
|
planetName: report.originPlanetName
|
||||||
|
})) {
|
||||||
|
mutated = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updatePlanetIdField(report as unknown as Record<string, unknown>, 'targetPlanetId', idMap, {
|
||||||
|
position: report.targetPosition,
|
||||||
|
planetName: report.targetPlanetName
|
||||||
|
})) {
|
||||||
|
mutated = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (report.details?.newPlanetId) {
|
||||||
|
const remappedNewPlanetId = resolveRemappedPlanetId(report.details.newPlanetId, idMap, {
|
||||||
|
position: report.targetPosition,
|
||||||
|
planetName: report.details.newPlanetName || report.targetPlanetName
|
||||||
|
})
|
||||||
|
|
||||||
|
if (remappedNewPlanetId && remappedNewPlanetId !== report.details.newPlanetId) {
|
||||||
|
report.details.newPlanetId = remappedNewPlanetId
|
||||||
|
mutated = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return mutated
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修复玩家星球的重复ID,并同步更新可被可靠识别的旧引用。
|
||||||
|
* 缺少位置或名称上下文、无法安全判定归属的旧引用会保留原ID,
|
||||||
|
* 继续指向保留下来的首个星球,避免把数据误指到错误目标。
|
||||||
|
*/
|
||||||
|
const fixDuplicatePlanetIds = (data: MigratableGameData): boolean => {
|
||||||
|
const player = data.player
|
||||||
|
if (!player || !Array.isArray(player.planets) || player.planets.length === 0) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
const idMap = buildDuplicatePlanetIdMap(player)
|
||||||
|
if (idMap.size === 0) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
let mutated = true
|
||||||
|
|
||||||
|
player.planets.forEach(planet => {
|
||||||
|
if (planet.isMoon && updatePlanetIdField(planet as unknown as Record<string, unknown>, 'parentPlanetId', idMap, {
|
||||||
|
position: planet.position,
|
||||||
|
isMoon: false
|
||||||
|
})) {
|
||||||
|
mutated = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// 等待队列里的 planetId 应始终与所属星球保持一致
|
||||||
|
planet.waitingBuildQueue?.forEach(item => {
|
||||||
|
if (item.planetId && item.planetId !== planet.id) {
|
||||||
|
item.planetId = planet.id
|
||||||
|
mutated = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
if (updatePlanetIdField(data as unknown as Record<string, unknown>, 'currentPlanetId', idMap)) {
|
||||||
|
mutated = true
|
||||||
|
}
|
||||||
|
|
||||||
|
player.fleetMissions?.forEach(mission => {
|
||||||
|
if (updateMissionTargetPlanetId(mission, idMap)) {
|
||||||
|
mutated = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
player.spyReports?.forEach(report => {
|
||||||
|
if (updateSpyReportTargetPlanetId(report, idMap)) {
|
||||||
|
mutated = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
player.spiedNotifications?.forEach(notification => {
|
||||||
|
if (updateSpiedNotificationTargetPlanetId(notification, idMap)) {
|
||||||
|
mutated = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
player.npcActivityNotifications?.forEach(notification => {
|
||||||
|
if (updateNPCActivityTargetPlanetId(notification, idMap)) {
|
||||||
|
mutated = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
player.missionReports?.forEach(report => {
|
||||||
|
if (updateMissionReportPlanetIds(report, idMap)) {
|
||||||
|
mutated = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
player.incomingFleetAlerts?.forEach(alert => {
|
||||||
|
if (updateIncomingAlertTargetPlanetId(alert, idMap)) {
|
||||||
|
mutated = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
player.jointAttackInvites?.forEach(invite => {
|
||||||
|
if (updateJointAttackTargetPlanetId(invite, idMap)) {
|
||||||
|
mutated = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
player.allyDefenseNotifications?.forEach(notification => {
|
||||||
|
if (updateAllyDefenseTargetPlanetId(notification, idMap)) {
|
||||||
|
mutated = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
data.npcs?.forEach(npc => {
|
||||||
|
if (npc.playerSpyReports) {
|
||||||
|
// playerSpyReports 的 key 就是玩家星球 ID,需要和报告内容一起迁移
|
||||||
|
const remappedPlayerSpyReports: Record<string, SpyReport> = {}
|
||||||
|
|
||||||
|
Object.entries(npc.playerSpyReports).forEach(([planetId, report]) => {
|
||||||
|
if (updateSpyReportTargetPlanetId(report, idMap)) {
|
||||||
|
mutated = true
|
||||||
|
}
|
||||||
|
|
||||||
|
const remappedPlanetId = resolveRemappedPlanetId(planetId, idMap, {
|
||||||
|
position: report.targetPosition,
|
||||||
|
planetName: report.targetPlanetName
|
||||||
|
})
|
||||||
|
|
||||||
|
if (remappedPlanetId && remappedPlanetId !== planetId) {
|
||||||
|
remappedPlayerSpyReports[remappedPlanetId] = report
|
||||||
|
mutated = true
|
||||||
|
} else {
|
||||||
|
remappedPlayerSpyReports[planetId] = report
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
npc.playerSpyReports = remappedPlayerSpyReports
|
||||||
|
}
|
||||||
|
|
||||||
|
npc.fleetMissions?.forEach(mission => {
|
||||||
|
if (updateMissionTargetPlanetId(mission, idMap)) {
|
||||||
|
mutated = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
return mutated
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 执行数据迁移
|
* 执行数据迁移
|
||||||
* 将旧版本的 universePlanets 和 debrisFields 从 gameStore 迁移到 universeStore
|
* 将旧版本的 universePlanets 和 debrisFields 从 gameStore 迁移到 universeStore
|
||||||
@@ -22,13 +408,13 @@ export const migrateGameData = (): void => {
|
|||||||
if (!oldEncryptedData) return
|
if (!oldEncryptedData) return
|
||||||
|
|
||||||
// 尝试解密(如果是加密格式)
|
// 尝试解密(如果是加密格式)
|
||||||
let oldData: any
|
let oldData: MigratableGameData
|
||||||
try {
|
try {
|
||||||
oldData = decryptData(oldEncryptedData)
|
oldData = decryptData(oldEncryptedData) as MigratableGameData
|
||||||
} catch {
|
} catch {
|
||||||
// 解密失败,可能是新格式(未加密),直接解析
|
// 解密失败,可能是新格式(未加密),直接解析
|
||||||
try {
|
try {
|
||||||
oldData = JSON.parse(oldEncryptedData)
|
oldData = JSON.parse(oldEncryptedData) as MigratableGameData
|
||||||
} catch {
|
} catch {
|
||||||
return // 无法解析,放弃迁移
|
return // 无法解析,放弃迁移
|
||||||
}
|
}
|
||||||
@@ -101,55 +487,9 @@ export const migrateGameData = (): void => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 修复重复的星球ID
|
// 修复重复的星球ID
|
||||||
if (oldData.player?.planets && Array.isArray(oldData.player.planets)) {
|
if (fixDuplicatePlanetIds(oldData)) {
|
||||||
const planetsByOriginalId = new Map<string, Planet[]>()
|
|
||||||
|
|
||||||
// 第一步:按ID分组
|
|
||||||
oldData.player.planets.forEach((planet: Planet) => {
|
|
||||||
if (!planetsByOriginalId.has(planet.id)) {
|
|
||||||
planetsByOriginalId.set(planet.id, [])
|
|
||||||
}
|
|
||||||
planetsByOriginalId.get(planet.id)!.push(planet)
|
|
||||||
})
|
|
||||||
|
|
||||||
// 第二步:处理重复ID并建立映射
|
|
||||||
const idMap = new Map<string, string>() // Key: oldId_galaxy:system:position -> Value: newId
|
|
||||||
|
|
||||||
planetsByOriginalId.forEach((planets, originalId) => {
|
|
||||||
if (planets.length > 1) {
|
|
||||||
// 对重复组中的星球,保留第一个,修改后续的
|
|
||||||
planets.forEach((planet, index) => {
|
|
||||||
if (index > 0) {
|
|
||||||
const newId = `${originalId}_${Math.random().toString(36).substring(2, 9)}`
|
|
||||||
const posKey = `${planet.position.galaxy}:${planet.position.system}:${planet.position.position}`
|
|
||||||
// 记录映射:原始ID + 坐标 -> 新ID
|
|
||||||
idMap.set(`${originalId}_${posKey}`, newId)
|
|
||||||
|
|
||||||
// 修改星球ID
|
|
||||||
planet.id = newId
|
|
||||||
needsSave = true
|
needsSave = true
|
||||||
}
|
}
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// 第三步:更新月球的 parentPlanetId
|
|
||||||
if (idMap.size > 0) {
|
|
||||||
oldData.player.planets.forEach((planet: Planet) => {
|
|
||||||
if (planet.isMoon && planet.parentPlanetId) {
|
|
||||||
// 假设月球和母星坐标一致,通过月球坐标查找母星的新ID
|
|
||||||
const posKey = `${planet.position.galaxy}:${planet.position.system}:${planet.position.position}`
|
|
||||||
const mapKey = `${planet.parentPlanetId}_${posKey}`
|
|
||||||
|
|
||||||
const newParentId = idMap.get(mapKey)
|
|
||||||
if (newParentId) {
|
|
||||||
planet.parentPlanetId = newParentId
|
|
||||||
needsSave = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 迁移温度数据:为没有温度的星球生成温度
|
// 迁移温度数据:为没有温度的星球生成温度
|
||||||
// 玩家星球
|
// 玩家星球
|
||||||
@@ -215,10 +555,11 @@ export const migrateGameData = (): void => {
|
|||||||
// 新版本统一使用 npc.relations[playerId] 存储NPC对玩家的关系
|
// 新版本统一使用 npc.relations[playerId] 存储NPC对玩家的关系
|
||||||
if (oldData.player?.diplomaticRelations && oldData.npcs && Array.isArray(oldData.npcs)) {
|
if (oldData.player?.diplomaticRelations && oldData.npcs && Array.isArray(oldData.npcs)) {
|
||||||
const playerId = oldData.player.id
|
const playerId = oldData.player.id
|
||||||
|
const npcs = oldData.npcs
|
||||||
const playerRelations = oldData.player.diplomaticRelations as Record<string, any>
|
const playerRelations = oldData.player.diplomaticRelations as Record<string, any>
|
||||||
|
|
||||||
Object.entries(playerRelations).forEach(([npcId, relation]) => {
|
Object.entries(playerRelations).forEach(([npcId, relation]) => {
|
||||||
const npc = oldData.npcs.find((n: NPC) => n.id === npcId)
|
const npc = npcs.find((n: NPC) => n.id === npcId)
|
||||||
if (npc) {
|
if (npc) {
|
||||||
if (!npc.relations) {
|
if (!npc.relations) {
|
||||||
npc.relations = {}
|
npc.relations = {}
|
||||||
|
|||||||
@@ -708,30 +708,30 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 按关系状态分类NPC(同时应用搜索过滤)
|
// 按关系状态分类NPC(同时应用搜索过滤)
|
||||||
const allNpcs = computed(() => sortNpcs(npcStore.npcs.filter(matchesSearch)))
|
// 先统一排序一次,避免不同标签页在同一批数据上重复排序
|
||||||
|
const sortedNpcs = computed(() => sortNpcs(npcStore.npcs.filter(matchesSearch)))
|
||||||
|
|
||||||
|
const allNpcs = computed(() => sortedNpcs.value)
|
||||||
|
|
||||||
const friendlyNpcs = computed(() => {
|
const friendlyNpcs = computed(() => {
|
||||||
return sortNpcs(npcStore.npcs.filter(npc => {
|
return sortedNpcs.value.filter(npc => {
|
||||||
if (!matchesSearch(npc)) return false
|
|
||||||
const relation = getRelation(npc.id)
|
const relation = getRelation(npc.id)
|
||||||
return relation?.status === RelationStatus.Friendly
|
return relation?.status === RelationStatus.Friendly
|
||||||
}))
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
const neutralNpcs = computed(() => {
|
const neutralNpcs = computed(() => {
|
||||||
return sortNpcs(npcStore.npcs.filter(npc => {
|
return sortedNpcs.value.filter(npc => {
|
||||||
if (!matchesSearch(npc)) return false
|
|
||||||
const relation = getRelation(npc.id)
|
const relation = getRelation(npc.id)
|
||||||
return !relation || relation.status === RelationStatus.Neutral
|
return !relation || relation.status === RelationStatus.Neutral
|
||||||
}))
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
const hostileNpcs = computed(() => {
|
const hostileNpcs = computed(() => {
|
||||||
return sortNpcs(npcStore.npcs.filter(npc => {
|
return sortedNpcs.value.filter(npc => {
|
||||||
if (!matchesSearch(npc)) return false
|
|
||||||
const relation = getRelation(npc.id)
|
const relation = getRelation(npc.id)
|
||||||
return relation?.status === RelationStatus.Hostile
|
return relation?.status === RelationStatus.Hostile
|
||||||
}))
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
// 分页辅助函数
|
// 分页辅助函数
|
||||||
|
|||||||
@@ -552,6 +552,8 @@
|
|||||||
})
|
})
|
||||||
} else if (section.tabValue === 'ships') {
|
} else if (section.tabValue === 'ships') {
|
||||||
if (!selectedPlanet.value) return
|
if (!selectedPlanet.value) return
|
||||||
|
// 某些过滤场景下舰船列表可能为空,避免平均分配时除以 0
|
||||||
|
if (!section.items.length) return
|
||||||
|
|
||||||
// 重新计算最大舰队仓储,确保数据是最新的
|
// 重新计算最大舰队仓储,确保数据是最新的
|
||||||
const maxStorage = calculateMaxFleetStorage(selectedPlanet.value, gameStore.player.technologies)
|
const maxStorage = calculateMaxFleetStorage(selectedPlanet.value, gameStore.player.technologies)
|
||||||
|
|||||||
Reference in New Issue
Block a user