Files
test1/game/ui/EndScreenModal.ts

172 lines
5.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 游戏结束模态弹窗(胜利 / 失败)
* DOM 层实现z-index: 9998覆盖 canvas
*/
export interface VictoryData {
kpi: number
hc: number
grade: string
gradeColor: string
gradeDesc: string
}
function injectEndStyles(): void {
if (document.getElementById('end-screen-styles')) return
const style = document.createElement('style')
style.id = 'end-screen-styles'
style.textContent = `
@keyframes endOverlayIn { from { opacity: 0 } to { opacity: 1 } }
@keyframes endCardIn { from { transform: scale(0.8); opacity: 0 } to { transform: scale(1); opacity: 1 } }
`
document.head.appendChild(style)
}
function buildOverlay(): HTMLElement {
const overlay = document.createElement('div')
overlay.id = 'end-screen-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: endOverlayIn 0.4s ease;
`
return overlay
}
function buildVictoryCard(data: VictoryData): HTMLElement {
const card = document.createElement('div')
card.style.cssText = `
background: #0f0c29;
border: 2px solid #d97706;
border-radius: 14px;
padding: 36px 48px;
max-width: 480px;
width: 90%;
text-align: center;
box-shadow: 0 0 60px rgba(217,119,6,0.4);
animation: endCardIn 0.4s ease;
`
card.innerHTML = `
<div style="font-size:32px;color:#fbbf24;letter-spacing:4px;margin-bottom:24px;">绩效评级公示</div>
<div style="background:rgba(255,255,255,0.04);border-radius:8px;padding:16px;margin-bottom:20px;">
<div style="display:flex;justify-content:space-between;font-size:20px;color:#9ca3af;margin-bottom:6px;">
<span>最终KPI</span><span style="color:#e2e8f0">${data.kpi}%</span>
</div>
<div style="display:flex;justify-content:space-between;font-size:20px;color:#9ca3af;">
<span>剩余HC</span><span style="color:#86efac">${data.hc}</span>
</div>
</div>
<div style="font-size:28px;color:${data.gradeColor};margin-bottom:10px;text-shadow:0 0 12px ${data.gradeColor}88;">
${data.grade}
</div>
<div style="font-size:16px;color:#9ca3af;margin-bottom:28px;">${data.gradeDesc}</div>
`
const btnWrap = document.createElement('div')
btnWrap.style.cssText = 'display:flex;gap:16px;justify-content:center;'
const restartBtn = document.createElement('button')
restartBtn.textContent = '再战一局'
restartBtn.style.cssText = `
padding:12px 28px;background:#7c3aed;color:#fff;border:2px solid #7c3aed;
border-radius:8px;font-family:'VT323',monospace;font-size:20px;cursor:pointer;
`
restartBtn.addEventListener('click', () => window.location.reload())
const homeBtn = document.createElement('button')
homeBtn.textContent = '见好就收'
homeBtn.style.cssText = `
padding:12px 28px;background:#374151;color:#d1d5db;border:1px solid #4b5563;
border-radius:8px;font-family:'VT323',monospace;font-size:20px;cursor:pointer;
`
homeBtn.addEventListener('click', () => { window.location.href = '/' })
btnWrap.appendChild(restartBtn)
btnWrap.appendChild(homeBtn)
card.appendChild(btnWrap)
return card
}
function buildDefeatCard(): HTMLElement {
const card = document.createElement('div')
card.style.cssText = `
background: #ffffff;
border-radius: 14px;
max-width: 420px;
width: 90%;
overflow: hidden;
box-shadow: 0 20px 60px rgba(0,0,0,0.5);
animation: endCardIn 0.4s ease;
`
const topBar = document.createElement('div')
topBar.textContent = '系统通知 — 人力资源管理系统'
topBar.style.cssText = `
background: #1677ff;
color: #fff;
font-family: 'VT323', monospace;
font-size: 18px;
padding: 10px 20px;
letter-spacing: 2px;
`
card.appendChild(topBar)
const body = document.createElement('div')
body.style.cssText = 'padding: 28px 32px 24px;'
body.innerHTML = `
<div style="font-size:48px;text-align:center;margin-bottom:16px;">📋</div>
<div style="font-family:'VT323',monospace;font-size:18px;color:#333;line-height:1.7;margin-bottom:24px;text-align:center;">
鉴于您近期的表现未能达成业务闭环,<br/>
经公司管理层研究决定,<br/>
对您进行<strong style="color:#ef4444">「毕业」</strong>处理。<br/>
请于5分钟内归还工牌<br/>
不要带走办公文具。
</div>
`
const btnWrap = document.createElement('div')
btnWrap.style.cssText = 'display:flex;gap:12px;justify-content:center;'
const restartBtn = document.createElement('button')
restartBtn.textContent = '领取 N+1'
restartBtn.style.cssText = `
padding:10px 24px;background:#1677ff;color:#fff;border:none;
border-radius:6px;font-family:'VT323',monospace;font-size:20px;cursor:pointer;
`
restartBtn.addEventListener('click', () => window.location.reload())
const homeBtn = document.createElement('button')
homeBtn.textContent = '申请仲裁'
homeBtn.style.cssText = `
padding:10px 24px;background:#f3f4f6;color:#374151;border:1px solid #d1d5db;
border-radius:6px;font-family:'VT323',monospace;font-size:20px;cursor:pointer;
`
homeBtn.addEventListener('click', () => { window.location.href = '/' })
btnWrap.appendChild(restartBtn)
btnWrap.appendChild(homeBtn)
body.appendChild(btnWrap)
card.appendChild(body)
return card
}
/** 显示胜利结算弹窗 */
export function showVictoryModal(data: VictoryData): void {
injectEndStyles()
const overlay = buildOverlay()
overlay.appendChild(buildVictoryCard(data))
document.body.appendChild(overlay)
}
/** 显示失败结算弹窗 */
export function showDefeatModal(): void {
injectEndStyles()
const overlay = buildOverlay()
overlay.appendChild(buildDefeatCard())
document.body.appendChild(overlay)
}