import type { MapConfig } from '../data/mapConfigs' import { ALL_MAPS } from '../data/mapConfigs' import { GameManager } from '../GameManager' /** * 地图切换过渡弹窗(DOM 层,覆盖 canvas) * 显示当前地图通关信息,3秒后自动关闭并触发下一张地图加载 */ export class MapTransitionModal { private container: HTMLElement | null = null private autoCloseTimer: ReturnType | null = null /** * 显示地图过关弹窗 * @param clearedMap 刚通关的地图配置 * @param onNext 3秒后自动触发的回调(加载下一张地图) */ show(clearedMap: MapConfig, onNext: () => void): void { this.cleanup() const manager = GameManager.getInstance() const nextMapIndex = manager.currentMapIndex + 1 const nextMap = ALL_MAPS[nextMapIndex] const isFinalMap = !nextMap this.createDOM(clearedMap, nextMap ?? null, isFinalMap, onNext) } private createDOM( clearedMap: MapConfig, nextMap: MapConfig | null, isFinalMap: boolean, onNext: () => void ): void { const manager = GameManager.getInstance() const kpi = manager.kpi const hcReward = 100 const overlay = document.createElement('div') overlay.id = 'map-transition-overlay' overlay.style.cssText = ` position: fixed; inset: 0; background: rgba(0,0,0,0.85); z-index: 9998; display: flex; align-items: center; justify-content: center; font-family: 'VT323', monospace; animation: mtFadeIn 0.4s ease; ` const card = document.createElement('div') card.style.cssText = ` background: #0f1b2d; border: 2px solid #7c3aed; border-radius: 16px; padding: 36px 48px; max-width: 520px; width: 90%; box-shadow: 0 0 60px rgba(124,58,237,0.6); text-align: center; animation: mtSlideIn 0.4s ease; ` // 过关标题 const titleEl = document.createElement('div') titleEl.textContent = isFinalMap ? '全部通关!最终胜利!' : `过关!` titleEl.style.cssText = ` font-size: 36px; color: #fbbf24; margin-bottom: 8px; letter-spacing: 3px; ` card.appendChild(titleEl) // 地图名称 const mapNameEl = document.createElement('div') mapNameEl.textContent = `「${clearedMap.name}」已清场` mapNameEl.style.cssText = ` font-size: 22px; color: #a78bfa; margin-bottom: 20px; ` card.appendChild(mapNameEl) // 分割线 const hr = document.createElement('div') hr.style.cssText = ` height: 1px; background: linear-gradient(90deg, transparent, #7c3aed, transparent); margin-bottom: 16px; ` card.appendChild(hr) // KPI & 奖励 const statsEl = document.createElement('div') statsEl.innerHTML = `KPI: ${kpi}%  |  获得奖励: +${hcReward} HC` statsEl.style.cssText = ` font-size: 20px; color: #e2e8f0; margin-bottom: 24px; ` card.appendChild(statsEl) // 下一关提示 / 最终胜利提示 const nextEl = document.createElement('div') if (isFinalMap) { nextEl.textContent = '恭喜完成全部关卡!你是真正的打工人传奇!' nextEl.style.cssText = ` font-size: 18px; color: #fbbf24; background: rgba(251,191,36,0.1); border: 1px solid #fbbf24; border-radius: 8px; padding: 12px 16px; margin-bottom: 20px; ` } else { nextEl.innerHTML = `下一关: ${nextMap!.name}` nextEl.style.cssText = ` font-size: 20px; color: #e2e8f0; background: rgba(96,165,250,0.1); border: 1px solid #3b82f6; border-radius: 8px; padding: 12px 16px; margin-bottom: 20px; ` } card.appendChild(nextEl) // 倒计时提示 const countdownEl = document.createElement('div') countdownEl.id = 'mt-countdown' countdownEl.textContent = isFinalMap ? '3秒后返回主菜单...' : '3秒后自动进入下一关...' countdownEl.style.cssText = ` font-size: 16px; color: #6b7280; ` card.appendChild(countdownEl) // 注入动画 const style = document.createElement('style') style.textContent = ` @keyframes mtFadeIn { from { opacity: 0 } to { opacity: 1 } } @keyframes mtSlideIn { from { transform: scale(0.85); opacity: 0 } to { transform: scale(1); opacity: 1 } } ` document.head.appendChild(style) overlay.appendChild(card) document.body.appendChild(overlay) this.container = overlay // 给 HC 奖励 manager.addHC(hcReward) // 3秒自动触发 let remaining = 3 const tick = () => { remaining-- const el = document.getElementById('mt-countdown') if (el) el.textContent = isFinalMap ? `${remaining}秒后返回主菜单...` : `${remaining}秒后自动进入下一关...` } const interval = setInterval(tick, 1000) this.autoCloseTimer = setTimeout(() => { clearInterval(interval) this.cleanup() onNext() }, 3000) } cleanup(): void { if (this.autoCloseTimer !== null) { clearTimeout(this.autoCloseTimer) this.autoCloseTimer = null } const el = document.getElementById('map-transition-overlay') if (el) el.remove() this.container = null } destroy(): void { this.cleanup() } }