feat(game/ui): 升级胜利/失败结算界面,胜利弹窗显示绩效等级评定,失败弹窗仿钉钉风格
This commit is contained in:
171
game/ui/EndScreenModal.ts
Normal file
171
game/ui/EndScreenModal.ts
Normal file
@@ -0,0 +1,171 @@
|
||||
/**
|
||||
* 游戏结束模态弹窗(胜利 / 失败)
|
||||
* 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)
|
||||
}
|
||||
Reference in New Issue
Block a user