v0.1.12: 弹框有道(ModalShell 统一壳 + 底部独立一排 + 全按钮检修)

【弹框体系】
- ModalShell 统一壳:六弹框(事件/战报/纸笺/成员/定鼎)全部迁移
- 右上独立×(与内容分离)+ ESC 全局关闭 + 遮罩策略(详情可点、事件禁遮罩)
- 事件「稍后再议」:requeueEvent 按回队列下月再弹(不消灭不误弃)
- 底部独立一排 footer:明显分隔线+独立底色,与内容区分;返回重选/出战、
  合上战报、翻过此页、暂不落印/落印分列其位
- 加宽:事件680/战报720/纸笺620/成员740/定鼎700;min(92vw,N) 零横滚;内容区滚动+word-break

【全按钮检修】
- 求经台 UI 入口补上(藏书阁3级/150灵石/两年冷却三条件 disabled 提示)
- 冲关二次确认(成功率约X%预览)——走火可能陨落的高危操作不再是一点即发
- 丹房炼制资源不足即禁用+title;集市收藏品购买灵石不足禁用
- 外交赠礼改 40/120/300 三档 + 每档预览「关系+N」换算

【测试】923→937(requeue 语义/赠礼档位矩阵/求经四态/弹框规格带)
金钟罩零漂移(纯 UI 层),typecheck/build 通过
This commit is contained in:
2026-08-23 12:03:59 +08:00
parent 12ab1e712a
commit 5fef79705b
13 changed files with 329 additions and 96 deletions
+38 -25
View File
@@ -6,6 +6,7 @@ import { describeRealm } from '../../game/data/realms'
import { Character } from '../../game/types/domain'
import { combatPowerOf } from '../../game/engine/systems/combat'
import { FORMATIONS, FormationId } from '../../game/data/formations'
import { ModalShell } from './ModalShell'
export function EventModal() {
const pendingEventId = useGameStore((s) => s.pendingEventId)
@@ -52,15 +53,42 @@ export function EventModal() {
)
}
const dorm = () => {
// 「稍后再议」:把事件按回队列,不消灭、不误弃
world.requeueEvent(pendingEventId)
closeModal()
}
return (
<div className="modal-outer">
<div className="modal">
<div className="modal-title">{pendingEventDef.name}</div>
<div className="modal-cat">
{eventCategoryName(pendingEventDef.category)}
{pendingEventDef.once && ' · 仅此一次'}
</div>
<div className="modal-text">{pendingEventDef.text}</div>
<ModalShell
title={pendingEventDef.name}
category={`${eventCategoryName(pendingEventDef.category)}${pendingEventDef.once ? ' · 仅此一次' : ''}`}
width={680}
allowOuter={false}
onClose={dorm}
closeLabel="稍后再议"
footer={
squadPicking ? (
<>
<button
className="btn"
onClick={() => {
setSquadPicking(false)
setSquadSel([])
}}
>
</button>
<button className="btn btn-primary" disabled={squadSel.length === 0} onClick={() => choose(raidIdx)}>
{squadSel.length === 0 ? '族中无可战之人' : `出战!(共${squadSel.length}人)`}
</button>
</>
) : (
<button className="btn" onClick={dorm}></button>
)
}
>
<div className="modal-text">{pendingEventDef.text}</div>
{squadPicking && (
<div className="modal-squad" style={{ marginBottom: 14 }}>
@@ -95,21 +123,7 @@ export function EventModal() {
<div className="modal-opts">
{squadPicking ? (
<>
<button className="opt-btn" onClick={() => choose(raidIdx)}>
{squadSel.length}
<span className="hint"></span>
</button>
<button
className="btn"
onClick={() => {
setSquadPicking(false)
setSquadSel([])
}}
>
</button>
</>
<div className="dim2"></div>
) : (
pendingEventDef.options.map((o, i) => {
const isRaid = raidIdx === i
@@ -123,7 +137,6 @@ export function EventModal() {
})
)}
</div>
</div>
</div>
</ModalShell>
)
}