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:
@@ -0,0 +1,101 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { World } from '../src/renderer/game/engine/world'
|
||||
import { calcGiftGain, GIFT_TIERS, giftNpc } from '../src/renderer/game/engine/systems/diplomacy'
|
||||
import { resetSaveBus, attachLogSink } from './world.helpers'
|
||||
|
||||
function baseWorld(seed: string): World {
|
||||
const w = World.create({ seed, surname: '霍', familyName: '霍家', motto: 'm', difficulty: 'normal' })
|
||||
resetSaveBus()
|
||||
attachLogSink(w)
|
||||
return w
|
||||
}
|
||||
|
||||
describe('0.1.12 弹框语义引擎', () => {
|
||||
it('requeueEvent:事件回队且清 pending 不重复', () => {
|
||||
const w = baseWorld('requeue')
|
||||
w.state.pendingEvent = 'ev-youdao'
|
||||
w.requeueEvent('ev-youdao')
|
||||
expect(w.state.pendingEvent).toBeUndefined()
|
||||
expect(w.state.eventQueue).toContain('ev-youdao')
|
||||
// 再次 requeue 不重复
|
||||
w.requeueEvent('ev-youdao')
|
||||
expect(w.state.eventQueue.filter((e) => e === 'ev-youdao').length).toBe(1)
|
||||
})
|
||||
|
||||
it('requeue 后事件可再次被 eventRoll 触发(monthly)', () => {
|
||||
const w = baseWorld('requeue2')
|
||||
w.state.pendingEvent = 'ev-youdao'
|
||||
w.requeueEvent('ev-youdao')
|
||||
// 下一月 eventRoll 会从队列抽出
|
||||
w.advanceMonth()
|
||||
expect(w.state.eventQueue).not.toContain('ev-youdao')
|
||||
})
|
||||
|
||||
it('事件关闭后(requeue)不算完成(可选择)', () => {
|
||||
const w = baseWorld('requeue3')
|
||||
const def = 'ev-lieshou'
|
||||
w.state.pendingEvent = def
|
||||
w.requeueEvent(def)
|
||||
expect(w.state.completedEvents).not.toContain(def)
|
||||
})
|
||||
})
|
||||
|
||||
describe('赠礼档位', () => {
|
||||
it.each(GIFT_TIERS.map((t) => [t] as const))('档位 %i 换算关系为 +N', (t) => {
|
||||
const gain = calcGiftGain(t)
|
||||
expect(gain).toBe(Math.max(1, Math.round(t / 12)))
|
||||
expect(gain).toBeGreaterThan(0)
|
||||
})
|
||||
|
||||
it.each(GIFT_TIERS.map((t) => [t] as const))('档位 %i 赠予后关系精确', (t) => {
|
||||
const w = baseWorld(`gift-${t}`)
|
||||
const npc = w.state.npcFamilies['n-xuanying']
|
||||
const before = npc.relation
|
||||
w.state.family.stones = 1000
|
||||
giftNpc(w, 'n-xuanying', t)
|
||||
expect(npc.relation).toBe(Math.min(100, before + calcGiftGain(t)))
|
||||
})
|
||||
|
||||
it('赠礼不足预算拒绝,分文不动', () => {
|
||||
const w = baseWorld('gift-poor')
|
||||
w.state.family.stones = 10
|
||||
const before = w.state.npcFamilies['n-xuanying'].relation
|
||||
const ok = giftNpc(w, 'n-xuanying', 40)
|
||||
expect(ok).toBe(false)
|
||||
expect(w.state.npcFamilies['n-xuanying'].relation).toBe(before)
|
||||
})
|
||||
})
|
||||
|
||||
describe('求经台按钮条件', () => {
|
||||
it('藏书阁不足 3 级拒绝(seekSutra 路径)', () => {
|
||||
const w = baseWorld('sutra-low')
|
||||
w.state.family.buildings = { cangshu: 2 }
|
||||
expect(w.seekSutra()).toBe(false)
|
||||
})
|
||||
|
||||
it('藏书阁 3 级 + 灵石足够 + 冷却期外成功', () => {
|
||||
const w = baseWorld('sutra-ok')
|
||||
w.state.family.buildings = { cangshu: 3 }
|
||||
w.state.family.stones = 1000
|
||||
expect(w.seekSutra()).toBe(true)
|
||||
expect(w.state.family.stones).toBe(850)
|
||||
})
|
||||
|
||||
it('两年冷却内再访拒绝', () => {
|
||||
const w = baseWorld('sutra-cd')
|
||||
w.state.family.buildings = { cangshu: 3 }
|
||||
w.state.family.stones = 1000
|
||||
w.seekSutra()
|
||||
expect(w.seekSutra()).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
describe('ModalShell 规格约束(min(92vw,Npx) 类防横滚契约)', () => {
|
||||
it('弹框宽度定义均在 560-740 区间(可视化验收带)', () => {
|
||||
const widths = { event: 680, battle: 720, paper: 620, member: 740, resolve: 700, confirm: 560 }
|
||||
for (const [, w] of Object.entries(widths)) {
|
||||
expect(w).toBeGreaterThanOrEqual(540)
|
||||
expect(w).toBeLessThanOrEqual(760)
|
||||
}
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user